What happens
webcmd web fetch is dispatched on the client-owned fast path in src/main.ts:74, which calls runClientOwnedWebFetch directly. That function (src/fetch/command.ts:36) has no try/catch, and the call site is outside the CliError handling every other command routes through. Any thrown CliError therefore escapes to Node's default handler.
Reproduced on current main (0.5.4 build):
$ webcmd web fetch --url https://example.com
file:///…/dist/src/fetch/client.js:67
throw new CliError('FETCH_BLOCKED', 'The site blocked non-browser fetches.', …);
^
CliError: The site blocked non-browser fetches.
at webFetch (file:///…/dist/src/fetch/client.js:67:23)
at async runClientOwnedWebFetch (file:///…/dist/src/fetch/command.js:40:20)
at async file:///…/dist/src/main.js:74:9 {
code: 'FETCH_BLOCKED',
hint: 'Use webcmd web fetch-browser for this URL.',
exitCode: 1
}
Expected
The same shape every other command produces, so the code and hint are the signal and the internals are not:
Error: The site blocked non-browser fetches. (FETCH_BLOCKED)
Hint: Use webcmd web fetch-browser for this URL.
Why it matters
web fetch is the first call smart-search makes, so this is often the first error an agent sees in a session. A stack trace with absolute file paths and at async frames is many tokens of noise, buries the hint that tells the agent what to do next, and invites the agent to treat a routine block as a crash in webcmd itself.
Fix
Wrap runClientOwnedWebFetch in the same error handling the rest of the CLI uses, or move the client-owned path inside the existing handler. Applies to ArgumentError from clientOptions() too.
What happens
webcmd web fetchis dispatched on the client-owned fast path insrc/main.ts:74, which callsrunClientOwnedWebFetchdirectly. That function (src/fetch/command.ts:36) has no try/catch, and the call site is outside theCliErrorhandling every other command routes through. Any thrownCliErrortherefore escapes to Node's default handler.Reproduced on current
main(0.5.4 build):Expected
The same shape every other command produces, so the
codeandhintare the signal and the internals are not:Why it matters
web fetchis the first callsmart-searchmakes, so this is often the first error an agent sees in a session. A stack trace with absolute file paths andat asyncframes is many tokens of noise, buries thehintthat tells the agent what to do next, and invites the agent to treat a routine block as a crash in webcmd itself.Fix
Wrap
runClientOwnedWebFetchin the same error handling the rest of the CLI uses, or move the client-owned path inside the existing handler. Applies toArgumentErrorfromclientOptions()too.