Skip to content

fix(config): negatively cache deterministic hosted config rejections and stop reporting 4xx errors - #3719

Merged
kojiwakayama merged 2 commits into
mainfrom
fix/sentry-veryfront-server-e
Aug 14, 2026
Merged

fix(config): negatively cache deterministic hosted config rejections and stop reporting 4xx errors#3719
kojiwakayama merged 2 commits into
mainfrom
fix/sentry-veryfront-server-e

Conversation

@kojiwakayama

@kojiwakayama kojiwakayama commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Fixes VERYFRONT-SERVER-E (1,682 events / 7 users over 8 days, ongoing).

Root cause

A tenant's hosted veryfront.config uses a construct outside the declarative subset (any property access / new — e.g. routes.mode, process.env.X — maps to forbidden-capability: unsupported-call). The rejection is correct and deterministic (security boundary; no full-JS fallback for hosted tenants by design), but nothing about it was remembered: every request re-read source, re-spawned a permissionless worker, re-parsed with Babel, and re-rejected — 1,682 Sentry events, and a hammered broken config burns the 2-slot evaluator worker pool, pushing other tenants into SERVICE_OVERLOADED.

Fix

  • Negative LRU cache (config-failure-cache) for deterministic DeclarativeConfigEvaluationError rejections, keyed by the existing hostedCacheKey (configPath ‖ sourceDigest ‖ policyVersion ‖ fingerprint) — exactly the right key: a source-bound rejection can never become a success without the digest changing. Retryable infra failures (worker-timeout/overloaded) are NOT cached.
  • isExpectedApplicationError: 4xx VeryfrontErrors are no longer captured to Sentry (the tenant's 400 is their bug, not ours).

Testing (red-green TDD)

Four new negative-caching tests in loader.test.ts (deterministic rejection served from cache, exact production message asserted, infra failures still retried) + application-errors.test.ts coverage; all fail on pre-fix src (adversarial revert-check), pass at HEAD (109 steps loader, 14 passed observability).

Reviewer notes (from adversarial verification)

  • The 4xx suppression applies to every VeryfrontError at every captureApplicationError boundary (proxy, SSR, runtime handler, agent) — genuine server-side bugs surfacing as 4xx (mis-issued internal auth → 401, unexpected 404/429 storms) will no longer reach Sentry. Deliberate, but wider than SERVER-E strictly required; consider keeping some 4xx slugs reportable.
  • The cached rejection is a shared error instance; each request wraps it in a fresh VeryfrontError downstream (test-asserted), so the shared stack is harmless.

Note: the stacked PR fix/sentry-tenant-error-capture builds on this branch.

Summary by CodeRabbit

  • Bug Fixes

    • Improved hosted configuration handling by reusing deterministic evaluation failures, re-evaluating after configuration changes, and retrying transient infrastructure failures.
    • Prevented expected client-side configuration errors from being reported as application errors, while continuing to report server-side initialization and unexpected errors.
  • Documentation

    • Updated observability API reference links to point to the correct source locations.
  • Tests

    • Added coverage for hosted configuration failure caching, cache clearing, retries, and application-error classification.

…and stop reporting 4xx errors

A hosted veryfront.config that the declarative evaluator deterministically
rejects (e.g. forbidden-capability: unsupported-call) was re-read, re-hashed
and re-sent to the evaluator worker on every request, because only successful
evaluations were cached. Each per-request rethrow at the renderer.request
boundary also produced a Sentry event even though CONFIG_PARSE_ERROR is a
status-400 tenant-content failure.

- Add a negative cache next to the positive hosted config cache, keyed by the
  same source-digest/policy/fingerprint cache key so a corrected config or a
  new release self-invalidates the entry. Worker-phase and retryable failures
  are never cached.
- Treat client-class (4xx) VeryfrontErrors as expected in
  captureApplicationError so tenant-content failures no longer flood the
  error tracker; they remain logged at their throw sites.

Fixes VERYFRONT-SERVER-E
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 38364e6d-1526-463b-91fd-c0ccacbc6471

📥 Commits

Reviewing files that changed from the base of the PR and between 4eece1f and 91e0eb2.

📒 Files selected for processing (5)
  • docs/api-reference/veryfront/observability.md
  • src/config/loader.test.ts
  • src/config/loader.ts
  • src/observability/application-errors.test.ts
  • src/observability/application-errors.ts

📝 Walkthrough

Walkthrough

Changes

Hosted configuration negative cache

Layer / File(s) Summary
Failure cache and eligibility
src/config/loader.ts
Adds a monitored LRU cache for deterministic hosted configuration failures and excludes retryable worker-phase errors.
Evaluation and invalidation flow
src/config/loader.ts
Reads cached failures before evaluation, stores eligible failures after evaluation, and clears them with clearConfigCache.
Negative-cache behavior tests
src/config/loader.test.ts
Tests rejection reuse, source-change re-evaluation, cache clearing, and retryable failure recovery.

Application-error classification

Layer / File(s) Summary
Expected error filtering and documentation
src/observability/application-errors.ts, src/observability/application-errors.test.ts, docs/api-reference/veryfront/observability.md
Excludes client-class VeryfrontError instances with 4xx statuses from reporting, preserves server and ordinary error reporting, and updates observability source links.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: 🔵 Low · up to 91e0e

The PR adds deterministic rejection caching and stops reporting 4xx application errors; it is otherwise mergeable, but suppressing all 4xx errors could hide genuine server-side failures, so owner awareness or follow-up to narrow reportable cases is warranted.

Sequence Diagram(s)

sequenceDiagram
  participant HostedSourceEvaluation
  participant HostedConfigFailureCache
  participant HostedConfigurationFlight
  HostedSourceEvaluation->>HostedConfigFailureCache: Check project key and revision
  HostedSourceEvaluation->>HostedConfigurationFlight: Evaluate when no cached failure exists
  HostedConfigurationFlight->>HostedConfigFailureCache: Store deterministic failure
Loading

Possibly related PRs

Suggested reviewers: kwakayama

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes both main changes: negative caching for deterministic hosted config rejections and suppression of Sentry reporting for 4xx errors.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sentry-veryfront-server-e

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown

📦 Client bundle boundary

Entrypoint Modules Source size Server leaks
src/index.client.ts 454 3065 KiB ⚠️ 39 known

A server module in a client graph aborts hydration in the browser. New leaks fail CI; known leaks are tracked in scripts/lint/client-bundle-baseline.json to burn down.

The application error capture change shifted exported observability source anchors, and CI checks generated API reference files with the pinned Deno 2.7.7 toolchain. Regenerating only the stale observability reference keeps the stacked PR narrow while clearing the failing docs check.

Constraint: PR #3723 is stacked on this branch, so the fix must avoid broad generated churn.

Rejected: Commit docs generated by local Deno 2.7.12 | it rewrote anchors across 42 files and did not match CI's pinned generator output.

Confidence: high

Scope-risk: narrow

Tested: PATH=/tmp/deno-2.7.7-aarch64-apple-darwin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/Applications/VMware Fusion.app/Contents/Public:/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex-path:/Users/kojiwakayama/.codex/tmp/arg0/codex-arg0xChlGW:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx09/deno277/bin:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx13/deno277/bin:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx26-deno277/bin:/Users/kojiwakayama/Documents/CODE/agent-lab/.venv/bin:/Users/kojiwakayama/.veryfront/bin:/Users/kojiwakayama/.opencode/bin:/Users/kojiwakayama/.local/bin:/Users/kojiwakayama/.antigravity/antigravity/bin:/opt/homebrew/share/google-cloud-sdk/bin:/opt/homebrew/opt/openjdk/bin:/Users/kojiwakayama/.bun/bin:/Users/kojiwakayama/.krew/bin:/Applications/Visual Studio Code.app/Contents/Resources/app/bin:/Users/kojiwakayama/.nvm/versions/node/v24.18.0/bin:/Users/kojiwakayama/.cargo/bin:/Applications/Docker.app/Contents/Resources/bin/:/Users/kojiwakayama/.lmstudio/bin:/Applications/Warp.app/Contents/Resources/bin deno task lint:ci

Tested: PATH=/tmp/deno-2.7.7-aarch64-apple-darwin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/Applications/VMware Fusion.app/Contents/Public:/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex-path:/Users/kojiwakayama/.codex/tmp/arg0/codex-arg0xChlGW:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx09/deno277/bin:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx13/deno277/bin:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx26-deno277/bin:/Users/kojiwakayama/Documents/CODE/agent-lab/.venv/bin:/Users/kojiwakayama/.veryfront/bin:/Users/kojiwakayama/.opencode/bin:/Users/kojiwakayama/.local/bin:/Users/kojiwakayama/.antigravity/antigravity/bin:/opt/homebrew/share/google-cloud-sdk/bin:/opt/homebrew/opt/openjdk/bin:/Users/kojiwakayama/.bun/bin:/Users/kojiwakayama/.krew/bin:/Applications/Visual Studio Code.app/Contents/Resources/app/bin:/Users/kojiwakayama/.nvm/versions/node/v24.18.0/bin:/Users/kojiwakayama/.cargo/bin:/Applications/Docker.app/Contents/Resources/bin/:/Users/kojiwakayama/.lmstudio/bin:/Applications/Warp.app/Contents/Resources/bin deno test --preload=src/testing/preload.ts --no-check --allow-all --unstable-worker-options --unstable-net src/config/loader.test.ts src/observability/application-errors.test.ts

Tested: PATH=/tmp/deno-2.7.7-aarch64-apple-darwin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/Applications/VMware Fusion.app/Contents/Public:/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex-path:/Users/kojiwakayama/.codex/tmp/arg0/codex-arg0xChlGW:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx09/deno277/bin:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx13/deno277/bin:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx26-deno277/bin:/Users/kojiwakayama/Documents/CODE/agent-lab/.venv/bin:/Users/kojiwakayama/.veryfront/bin:/Users/kojiwakayama/.opencode/bin:/Users/kojiwakayama/.local/bin:/Users/kojiwakayama/.antigravity/antigravity/bin:/opt/homebrew/share/google-cloud-sdk/bin:/opt/homebrew/opt/openjdk/bin:/Users/kojiwakayama/.bun/bin:/Users/kojiwakayama/.krew/bin:/Applications/Visual Studio Code.app/Contents/Resources/app/bin:/Users/kojiwakayama/.nvm/versions/node/v24.18.0/bin:/Users/kojiwakayama/.cargo/bin:/Applications/Docker.app/Contents/Resources/bin/:/Users/kojiwakayama/.lmstudio/bin:/Applications/Warp.app/Contents/Resources/bin deno fmt --check docs/api-reference/veryfront/observability.md src/config/loader.ts src/config/loader.test.ts src/observability/application-errors.ts src/observability/application-errors.test.ts

Tested: git diff --check
@kojiwakayama
kojiwakayama marked this pull request as ready for review August 14, 2026 18:33
kojiwakayama added a commit that referenced this pull request Aug 14, 2026
The tenant capture branch is stacked on fix/sentry-veryfront-server-e, and the base advanced after the tenant-build classifier fix landed. Merge the updated base non-destructively so the PR tests and merge base reflect the current stack without rewriting the branch.

Constraint: Do not rebase or force-push the stacked PR branch.

Rejected: Rebase onto the updated base | would rewrite the PR branch history.

Confidence: high

Scope-risk: narrow

Directive: Keep #3723 stacked on #3719 until the lead asks to unstack or merge.

Tested: pending post-merge verification
@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 14, 2026
Merged via the queue into main with commit 033037c Aug 14, 2026
34 checks passed
@kojiwakayama
kojiwakayama deleted the fix/sentry-veryfront-server-e branch August 14, 2026 19:52
kojiwakayama added a commit that referenced this pull request Aug 14, 2026
The stacked config prerequisite landed on main as a squash commit, so this merge preserves the tenant-error classifier and its regressions while accepting the released config and documentation state. Generated observability references were rebuilt with the CI-pinned Deno toolchain after resolving the overlapping application-error test.

Constraint: #3719 merged by squash, so its branch commits are not ancestors of main

Rejected: Rebase or force-push the feature branch | rewriting reviewed history would make the repair harder to audit

Confidence: high

Scope-risk: narrow

Directive: Keep framework build failures error-level when changing tenant classification

Tested: focused observability, pipeline, MDX compiler, and config suites; pinned API-reference generation; fmt; lint; typecheck; diff-check

Not-tested: full pre-push hook runs on the resulting merge commit during push
@kojiwakayama kojiwakayama mentioned this pull request Aug 14, 2026
5 tasks
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