Skip to content

[wrangler] Reduce Sentry noise by classifying user-environment errors correctly#13835

Open
penalosa wants to merge 4 commits intomainfrom
sentry-noise-reduction
Open

[wrangler] Reduce Sentry noise by classifying user-environment errors correctly#13835
penalosa wants to merge 4 commits intomainfrom
sentry-noise-reduction

Conversation

@penalosa
Copy link
Copy Markdown
Contributor

@penalosa penalosa commented May 6, 2026

Summary

Converted common user-environment failures to UserError so they are no longer reported as crashes in Sentry. Also tightened top-level error filtering.

Changes

  • init.ts — C3 child-process delegation failures → UserError
  • start-remote-proxy-session.ts — preserves UserError identity across catch blocks
  • core/handle-errors.ts — duck-typed UserError detection, broader auth error matching (401/403), new filters for transient network errors, benign write errors, filesystem environment errors, and SSL certificate errors
  • cfetch/internal.ts — invalid API token characters (ByteString errors) caught and converted to UserError; KV/R2 4xx responses use APIError/UserError
  • assets.ts — missing assets directory at upload time → NonExistentAssetsDirError
  • autoconfig/frameworks/framework-class.ts — framework version detection failure → UserError
  • containers/ssh.ts — SSH errors (instance not found, auth failures, exit 255) → UserError
  • d1/export.ts — D1 export limitations → UserError
  • deployment-bundle/source-maps.ts — inline data-URL source maps → UserError

Author has addressed the following

  • Tests included/updated
  • Changeset included

… correctly

Converted common user-environment failures (missing build outputs, expired tokens, transient network issues, C3 process exits, invalid API tokens, missing assets directories, framework version detection, container SSH, D1 export limitations, and inline source maps) to UserError so they are no longer reported as crashes in Sentry. Also tightened top-level error filtering to recognise duck-typed UserError, MiniflareError.isUserError(), a broader set of authentication errors, transient network errors, and filesystem environment errors.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 6, 2026

🦋 Changeset detected

Latest commit: 2e149e9

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-project-automation github-project-automation Bot moved this to Untriaged in workers-sdk May 6, 2026
@penalosa penalosa marked this pull request as ready for review May 6, 2026 22:43
@penalosa penalosa requested a review from workers-devprod as a code owner May 6, 2026 22:43
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Changeset Review

Summary

✅ All changesets look good

Reviewed Changesets

Changeset Package(s) Version Notes
sentry-noise-reduction.md wrangler patch Good description of user-environment error classification
twenty-spies-rest.md workers-utils, wrangler minor New cache configuration feature - appropriate version
wrangler-containers-ssh-help-visible.md wrangler patch Clear bug fix description
fix-pages-routes-json-parse-error.md wrangler patch Clear error handling improvement
dependabot-update-13829.md miniflare, wrangler patch Dependency update - properly formatted
pipeline-stream-rename.md wrangler, workers-utils, miniflare minor Deprecation with good before/after examples
fix-wrangler-types-check-env-file.md wrangler patch Clear bug fix description
email-address-names.md miniflare minor New feature with code example
dependabot-update-13841.md miniflare, wrangler patch Dependency update - properly formatted
miniflare-default-tz-utc.md miniflare minor New feature with code example
wrangler-dev-tz-utc.md wrangler minor Behavior change - appropriate version
tame-grapes-vanish.md wrangler patch Clear bug fix description
fix-vite-plugin-dev-vars-quoting.md vite-plugin patch Clear bug fix description
wrangler-auth-scoped-account-list.md wrangler patch Clear behavior improvement description

Validation Results

  • Version Types: All appropriate (patch for fixes, minor for new features)
  • Changelog Quality: All have meaningful descriptions with context
  • Markdown Headers: No h1/h2/h3 headers found in any changeset
  • Analytics: No analytics-related changes detected
  • Dependabot: Two dependabot changesets present but for miniflare/wrangler (not create-cloudflare), properly formatted
  • Experimental features: None noted

@workers-devprod workers-devprod requested review from a team and emily-shen and removed request for a team May 6, 2026 22:43
@workers-devprod
Copy link
Copy Markdown
Contributor

workers-devprod commented May 6, 2026

Codeowners approval required for this PR:

  • @cloudflare/d1
  • ✅ @cloudflare/cloudchamber
  • ✅ @cloudflare/wrangler
Show detailed file reviewers
  • packages/wrangler/src/d1/export.ts: [@cloudflare/d1]

Copy link
Copy Markdown
Contributor

@ask-bonk ask-bonk Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm Bonk, and I've done a quick review of your PR.

This PR reclassifies a large set of user-environment errors as UserError to reduce Sentry noise, tightens error filtering in the top-level handler, and adds new predicates for transient network, benign write, and filesystem environment errors.

Issues

  1. Bug: isCloudflareAPIDNSError mixes e and err inside the visitErrorOrCause callback — The visitor callback receives the currently-visited node as err, but line 197 calls hasErrorCode(e, ...) (the outer top-level error), and lines 203–204 check "hostname" in e (again the outer e) while line 206 reads (err as { hostname }).hostname (the inner node). When e.cause has the ENOTFOUND code and hostname but e itself does not, the hostname check is evaluated against the wrong object. See suggestion below.

  2. Bug: dead UserError-preserving branch in start-remote-proxy-session.ts second catchmaybeError is a { error: unknown } wrapper, not an Error instance. maybeError instanceof UserError and maybeError instanceof Error are always false, so ErrorClass is always Error and the UserError branch is unreachable. The check should inspect maybeError.error instead.

Comment thread packages/wrangler/src/core/handle-errors.ts
@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented May 6, 2026

Review posted successfully on PR #13835. I found two bugs:

  1. isCloudflareAPIDNSError variable shadowing bug (handle-errors.ts:194-216) — Inside the visitErrorOrCause callback, e (outer error) and err (currently-visited node) are mixed up. hasErrorCode(e, ...) always checks the top-level error instead of the current node, and the hostname guard checks e for existence but reads from err. When the ENOTFOUND code/hostname lives on the cause, this evaluates against the wrong object.

  2. Dead UserError-preserving branch (start-remote-proxy-session.ts:91-95) — maybeError is a { error: unknown } wrapper object, so instanceof checks against it always return false. The code should check maybeError.error instead.

github run

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 6, 2026

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@13835

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@13835

miniflare

npm i https://pkg.pr.new/miniflare@13835

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@13835

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@13835

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@13835

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@13835

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@13835

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@13835

wrangler

npm i https://pkg.pr.new/wrangler@13835

commit: 2e149e9

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

View 5 additional findings in Devin Review.

Open in Devin Review

Comment thread packages/wrangler/src/core/handle-errors.ts Outdated
penalosa and others added 2 commits May 7, 2026 00:53
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ssion.ts

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@penalosa
Copy link
Copy Markdown
Contributor Author

penalosa commented May 7, 2026

/bonk fix the build errors on this PR

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented May 7, 2026

The build error was a syntax error in packages/wrangler/src/core/handle-errors.ts:212 — an extra closing brace } inside the isCloudflareAPIDNSError function's visitErrorOrCause callback. This caused the return undefined; statement to fall outside the callback body, producing a parse error:

Expected ")" but found "return"

The fix was simply removing the duplicate }. After the fix:

  • Build succeeds
  • Type-check passes
  • All 45 tests in handle-errors.test.ts pass

The other review-flagged bug (start-remote-proxy-session.ts instanceof on wrapper object) was already fixed in commit 60a0949.

github run

} catch (e) {
if (e instanceof TypeError && String(e.message).includes("ByteString")) {
throw new UserError(
"Your API token contains an invalid character. API tokens must be plain text.",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

include the header name in the error message?

if (errorCode !== undefined) {
apiError.code = errorCode;
}
if (response.status >= 400 && response.status < 500) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we make this check a lot, pull it out into a helper?

"code" in e &&
(e as { code: string }).code === "ENOENT"
) {
throw new NonExistentAssetsDirError(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not worth the noise, but i'd like to commemorate the one and only time a sentry alert actually led to me fixing a bug, after i released a dodgy C3 template and we got a bunch of errors here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

3 participants