Skip to content

fix(crawl): say a crawl with nothing new to follow completes, so users stop chasing their patterns - #50

Merged
StefanoGuerrini merged 14 commits into
mainfrom
fix/crawl-patterns-output-filter
Oct 16, 2026
Merged

StefanoGuerrini merged 14 commits into
mainfrom
fix/crawl-patterns-output-filter

Conversation

@zenrows-dev-pool

@zenrows-dev-pool zenrows-dev-pool Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Before: The Crawl API ended a crawl that kept nothing failed with no_items_found, so zenrows crawl wait exited 1 with CRAWL_FAILED and told the user to loosen their patterns. An earlier version of this PR also said patterns filter only the URLs a crawl returns, and that pages opened to walk past them count toward --max-pages and are billed. That is not how Crawl works.

After:

  • Patterns are described as on the base branch: repeatable substring filters on the URL. Nothing says the crawl opens or bills pages that fail them.
  • A crawl whose pages held nothing new to follow ends completed with 0 results. The CLI prints ok: true and exits 0.
  • When that crawl had --include-patterns or --exclude-patterns, the CLI adds a note (under --json, in note) to check them against the URLs the start page links to.
  • A failed no_items_found still exits 1 with CRAWL_FAILED. Its next_action now says the crawl read the start page but found no data it could use, and suggests starting from a listing or product page.
  • A failed seed_unreachable exits 1 with CRAWL_FAILED. Its next_action now also covers a start URL that returned an empty page.

How: Merged the current base into this branch with merge commits, twice. The second merge, of main, reported conflicts in skills/crawl/SKILL.md, src/cli/commands/crawl.ts and tests/crawl-command.test.ts. In each, main held the credit-stop change, now squash-merged there, and this branch held the same text plus the 0-result wording. The resolution kept both. crawlFailure carries the new next_action text for both codes. noMatchNote sets the patterns note only for a completed crawl with 0 items and patterns set. README, skills/crawl/SKILL.md and the help text drop the walk and billing wording. Acceptance row 19 and its surface check assert completed, 0 results, no error, exit 0 and a note.

Tests:

  • npm run typecheck: clean.
  • npm run build: clean.
  • npm test: 376 tests, 376 pass, 0 fail.
  • New and updated unit tests cover the patterns note, a no_items_found crawl, and an empty start page failing seed_unreachable.

`crawl create --output-format markdown` stores each kept URL's page
converted to Markdown, read back with `crawl content` and `crawl
download` as `--output-format html` already was. A value that is neither
is still refused locally, before any network call.

A crawl also reports `discovery`, the strategies it found URLs with, so
`crawl get --json` carries it instead of dropping it.
The lock names the API description this surface was synced to, by its
blob id, so a later drift check compares against it instead of reporting
the surface as never synced. Two operations in that description are not
served to callers and no surface exposes them; the lock lists them as
pending, so a change to either does not read as drift here.
The Crawl API now ends a crawl that runs out of credits, or whose API key
hits a credit cap, as `stopped` with `error.code` `insufficient_credits` or
`api_key_cap_reached` and no `stop_reason`, instead of `failed`. The CLI
treated every `stopped` crawl as a deliberate stop, so such a crawl would
have exited 0 with `ok: true`. It now exits 1 with `CRAWL_FAILED` and the
API's code as `server_code`, as it did when the crawl ended `failed`, with
next-step advice for both codes. `crawl stop` on such a crawl says it had
already ended. The crawl skill, the trace-debug skill and the README say so.
A crawl that ends `stopped` because the account ran out of credits or the
API key hit a credit cap now exits 1 with `CRAWL_INSUFFICIENT_CREDITS` or
`CRAWL_KEY_CAP_REACHED`, the codes a create refused with 402 already gets,
instead of `CRAWL_FAILED`. It carries the same next-step advice as those
codes, the API's `error.code` as `server_code`, its `error.detail` in
`likely_cause`, and `crawl_id`. A `failed` crawl with either of those
codes, as older deployments report it, maps the same way, so callers see
one code whatever the server version. Any other error on a stopped or
failed crawl stays `CRAWL_FAILED`.

`quotaExhausted` takes `status: null`, as `keyCapReached` does, for an
error read from a crawl rather than an HTTP 402. The crawl skill, the
trace-debug skill and the README say so.
The fixtures now carry the error.detail the server returns when credits end a crawl, one per error code.
The Crawl API now applies `include_patterns` and `exclude_patterns` only
to the URLs a crawl returns. The crawl still opens on-site pages that
fail them, to reach pages that match, and each of those fetches counts
toward `max_pages` and is billed. A crawl whose patterns match no URL it
read ends `completed` with no results instead of `failed` with
`no_items_found`, and `no_items_found` now only means the pages read held
nothing to follow.

`crawl get`, `crawl wait` and `create --follow` print a note when a
completed crawl with patterns kept nothing, telling the caller to loosen
the patterns or raise `--depth` or `--max-pages`. The exit code stays 0.
The `no_items_found` next action points at the start page instead of the
patterns. The `--max-pages` and pattern help, the README, the crawl skill
and acceptance check 19 say so.
zenrows-dev-pool Bot and others added 6 commits October 16, 2026 08:11
The lock lives beside the contract, not in a surface. main already
dropped it, and this branch had brought it back.
…imit the walk too

Patterns limit both the pages a crawl opens and the URLs it returns, so the
help, README and skill no longer say the crawl opens or bills pages that fail
them. A completed crawl with 0 results still exits 0, and with patterns set
its note says to check them against the URLs the start page links to.
no_items_found now means Extract found no data on the start page, and
seed_unreachable also covers an empty start page.
@zenrows-dev-pool zenrows-dev-pool Bot changed the title fix(crawl): treat patterns as a filter on the URLs a crawl returns fix(crawl): say a crawl with nothing new to follow completes, so users stop chasing their patterns Oct 16, 2026
Base automatically changed from fix/crawl-stopped-on-credits to main October 16, 2026 11:22
…tput-filter

# Conflicts:
#	skills/crawl/SKILL.md
#	src/cli/commands/crawl.ts
#	tests/crawl-command.test.ts
…y matches the API

The next_action and the skill now say the crawl read the start page but
found no data it could use, and suggest starting from a listing or product
page.
@StefanoGuerrini
StefanoGuerrini marked this pull request as ready for review October 16, 2026 13:56
@StefanoGuerrini
StefanoGuerrini merged commit 0301d47 into main Oct 16, 2026
4 checks passed
@StefanoGuerrini
StefanoGuerrini deleted the fix/crawl-patterns-output-filter branch October 16, 2026 14:06
@github-actions github-actions Bot mentioned this pull request Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant