Skip to content

observability: defer and flush Sentry sends so they survive the serverless freeze - #10972

Merged
lawrencecchen merged 1 commit into
mainfrom
feat-report-error-flush
Aug 27, 2026
Merged

lawrencecchen merged 1 commit into
mainfrom
feat-report-error-flush

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Live drills against production (deliberate vm_image_config_error after #10955 and #10968 deployed) produced the PostHog event but never a Sentry event. The project's event stream shows zero events since the manual sanity checks on 2026-08-06, across every reportError caller (coderouter, cloud VM, billing reconcile, vm-alerts webhook failures): the send was a floating promise with no flush, and the Vercel function freezes right after the response, so the SDK's queued envelope never left the process.

reportError now wraps the send in next/server after() (deferred past the response, so the flush costs no user-visible latency; fire-and-forget fallback where no request scope exists) and awaits Sentry.flush(2000).

Tests: bun test tests/vm-observability.test.ts tests/coderouter-sentry.test.ts, bun run typecheck clean. Will verify live with another drill once deployed.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Fixes Sentry error reporting in serverless functions so events reach Sentry instead of being dropped when the function freezes after the response. reportError now defers the send with after() and awaits Sentry.flush(2000); previously the send was a floating promise with no flush, so the Vercel function froze before the queued envelope left the process.

Bug Fixes

  • The send runs inside after() from next/server, so the 2s flush adds no user-visible latency within a request; outside a request scope it falls back to fire-and-forget.
  • The flush is awaited, ensuring the event leaves the process before the function freezes.

Written for commit d41cac1. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes
    • Improved error reporting reliability during requests by ensuring events are sent after request processing completes.
    • Added a brief delivery window for reporting events while preventing reporting failures from affecting the application.

… the lambda

reportError queued captureException on a floating promise with no flush.
On Vercel the function freezes right after the response, so the envelope
never left the process: the shared project has zero events since the
2026-08-06 manual sanity checks, across coderouter, cloud VM, billing, and
vm-alerts reporting. The send now runs inside next/server after() (so the
2s flush adds no user-visible latency) with a fire-and-forget fallback
outside request scope, and explicitly awaits Sentry.flush.
@cursor

cursor Bot commented Aug 27, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@coderabbitai

coderabbitai Bot commented Aug 27, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bc992506-0f91-4f75-818a-e3860726b1ce

📥 Commits

Reviewing files that changed from the base of the PR and between de3902d and d41cac1.

📒 Files selected for processing (1)
  • web/services/observability/report.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

The Sentry reporter now defers request-time reporting with Next.js after, waits for SDK initialization, flushes events for up to two seconds, and preserves non-throwing fire-and-forget behavior outside request contexts.

Changes

Observability reporting

Layer / File(s) Summary
Deferred Sentry sender
web/services/observability/report.ts
The reporter uses Next.js after during requests. It sends scrubbed context and fingerprints, flushes Sentry events for up to two seconds, and suppresses import, scheduling, and reporting failures.

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

Merge Risk: 🔵 Low · up to d41ca

This change improves Sentry delivery after serverless requests without affecting caller control flow or access controls. A bounded residual risk remains for error reports emitted outside request scope, which may still be lost if the process stops; the PR is mergeable with explicit owner awareness or follow-up.

Sequence Diagram(s)

sequenceDiagram
  participant Request as Request context
  participant After as Next.js after
  participant Reporter as Sentry reporter
  participant Sentry as Sentry SDK
  Request->>Reporter: Report scrubbed context and fingerprint
  Reporter->>After: Schedule reporting after response
  After->>Reporter: Run asynchronous sender
  Reporter->>Sentry: Load SDK and capture event
  Reporter->>Sentry: Flush events for up to two seconds
Loading
🚥 Pre-merge checks | ✅ 23 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description provides a clear summary, rationale, and testing details. It omits the required Demo Video for this behavior change, the Review Trigger section, and the Checklist. Add a Demo Video link or attachment that demonstrates the behavior change. Include the Review Trigger block and complete the Checklist items.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (23 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: deferring and flushing Sentry sends so events survive serverless function freezing.
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.
Cmux Swift Actor Isolation ✅ Passed PASS: The pull-request diff changes only web/services/observability/report.ts, which is TypeScript. It introduces no Swift production changes, so it cannot introduce or worsen any Swift 6 actor-isol…
Cmux Swift Blocking Runtime ✅ Passed PASS: The pull request changes only web/services/observability/report.ts, a TypeScript file. The diff contains no Swift paths and introduces no Swift blocking-runtime primitive. The `Sentry.flush(2_…
Cmux Browser Automation Off-Main ✅ Passed PASS: The pull request changes only web/services/observability/report.ts. The diff adds Sentry reporting with Next.js after() and Sentry.flush(2_000). It does not change browser socket automatio…
Cmux Expensive Synchronous Load ✅ Passed PASS: The pull request changes only web/services/observability/report.ts (+31/-15). It introduces TypeScript next/server and Sentry behavior, with no changed Swift files or Swift agent-history loa…
Cmux Cache Substitution Correctness ✅ Passed The check is not applicable. The only changed file is web/services/observability/report.ts. The diff changes Sentry loading, after() scheduling, and Sentry.flush(2_000). It does not replace an a…
Cmux No Hacky Sleeps ✅ Passed The diff introduces no sleep, setTimeout, setInterval, polling loop, or fixed backoff. after(send) uses Next.js request-lifecycle completion as the dispatch signal. Sentry.flush(2_000) is a bounde…
Cmux Algorithmic Complexity ✅ Passed PASS: The pull request changes only web/services/observability/report.ts. The added after(send), dynamic import, Sentry.flush(2_000), and error handling perform no collection scans. The only add…
Cmux Swift Concurrency ✅ Passed PASS: The pull-request diff against origin/main changes only web/services/observability/report.ts (+31/-15). It contains no Swift files and introduces no Swift concurrency patterns. The Swift-specific…
Cmux Swift @Concurrent ✅ Passed PASS: The pull request changes only web/services/observability/report.ts (31 additions, 15 deletions). The diff contains no Swift files or Swift concurrency annotations. Therefore, the Swift `@concu…
Cmux Swift Package Boundaries ✅ Passed PASS. The pull request changes only web/services/observability/report.ts (+31/-15). It introduces no Swift files, SwiftPM manifests, or app-target Swift logic. Therefore it cannot violate the Swift …
Cmux Swiftpm Lockfiles ✅ Passed PASS: The pull request changes only web/services/observability/report.ts (31 additions, 15 deletions). The diff contains no Package.swift, Package.resolved, .gitignore, workflow, or Xcode pr…
Cmux Swift Logging ✅ Passed PASS: The pull request changes only web/services/observability/report.ts; the commit diff contains no Swift files or Swift runtime code. The custom check applies only to logging introduced or materi…
Cmux User-Facing Error Privacy ✅ Passed PASS: The pull request changes only web/services/observability/report.ts. The diff changes Sentry scheduling and flushing, plus developer-only comments. It does not add or change user-facing errors,…
Cmux Full Internationalization ✅ Passed PASS. The commit changes only web/services/observability/report.ts. It adds Sentry scheduling and flushing, plus operational comments; it does not add or change user-facing UI text, API response cop…
Cmux Swiftui State Layout ✅ Passed PASS: The pull request changes only web/services/observability/report.ts, a TypeScript file. The diff introduces no SwiftUI view, state, layout measurement, list-row store reference, or render-time …
Cmux Architecture Rethink ✅ Passed PASS: The pull request changes only web/services/observability/report.ts, a TypeScript file. The commit diff contains no Swift, SwiftUI, AppKit, or Xcode-project paths. Therefore the Swift-specific …
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PASS: The pull request changes only web/services/observability/report.ts (+31/-15). The diff contains no Swift files and no NSWindow, NSPanel, NSWindowController, Window, or WindowGroup ch…
Cmux Source Artifacts ✅ Passed The diff changes only web/services/observability/report.ts. This is a hand-written application source file that adds Sentry reporting behavior. No local output, generated logs, screenshots, recordin…
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS — the custom check applies only to changed Swift files under production Sources/ paths. The pull-request diff contains one changed file, web/services/observability/report.ts, and contains no …
Cmux No Ambient Global State ✅ Passed PASS: The ambient-global-state policy applies to production Swift code. The pull-request diff contains exactly one changed file, web/services/observability/report.ts, and no .swift paths. Therefor…
Full details: Cmux Swift Actor Isolation

Explanation

PASS: The pull-request diff changes only web/services/observability/report.ts, which is TypeScript. It introduces no Swift production changes, so it cannot introduce or worsen any Swift 6 actor-isolation issue covered by the check.

Full details: Cmux Swift Blocking Runtime

Explanation

PASS: The pull request changes only web/services/observability/report.ts, a TypeScript file. The diff contains no Swift paths and introduces no Swift blocking-runtime primitive. The Sentry.flush(2_000) timing call is outside this Swift-specific check.

Full details: Cmux Browser Automation Off-Main

Explanation

PASS: The pull request changes only web/services/observability/report.ts. The diff adds Sentry reporting with Next.js after() and Sentry.flush(2_000). It does not change browser socket automation, WebKit/AppKit access, worker routing, processV2Command, or policy tests. The custom check is therefore inapplicable.

Full details: Cmux Expensive Synchronous Load

Explanation

PASS: The pull request changes only web/services/observability/report.ts (+31/-15). It introduces TypeScript next/server and Sentry behavior, with no changed Swift files or Swift agent-history load. The Swift-specific custom check is therefore inapplicable.

Full details: Cmux Cache Substitution Correctness

Explanation

The check is not applicable. The only changed file is web/services/observability/report.ts. The diff changes Sentry loading, after() scheduling, and Sentry.flush(2_000). It does not replace an authoritative read with a cached value and does not modify persistence, history, undo, or snapshot data paths. No cold-cache or stale-cache handling is therefore required.

Full details: Cmux No Hacky Sleeps

Explanation

The diff introduces no sleep, setTimeout, setInterval, polling loop, or fixed backoff. after(send) uses Next.js request-lifecycle completion as the dispatch signal. Sentry.flush(2_000) is a bounded SDK flush deadline that returns when the Sentry queue drains; it is not a fixed sleep. The changed code therefore does not match the explicit hacky-sleep failure condition.

Full details: Cmux Algorithmic Complexity

Explanation

PASS: The pull request changes only web/services/observability/report.ts. The added after(send), dynamic import, Sentry.flush(2_000), and error handling perform no collection scans. The only added collection operation, [...fingerprint] at line 33, copies a small diagnostic fingerprint; the production caller supplies three fixed elements. The recursive context scrubbing scans input data, but that logic is unchanged from the parent commit and is not worsened by this diff. No nested scan, per-target rescan, repeated sort/filter, in-memory join, or slower scalable algorithm was introduced.

Full details: Cmux Swift Concurrency

Explanation

PASS: The pull-request diff against origin/main changes only web/services/observability/report.ts (+31/-15). It contains no Swift files and introduces no Swift concurrency patterns. The Swift-specific custom check is not applicable.

Full details: Cmux Swift `@Concurrent`

Explanation

PASS: The pull request changes only web/services/observability/report.ts (31 additions, 15 deletions). The diff contains no Swift files or Swift concurrency annotations. Therefore, the Swift @concurrent check is not applicable.

Full details: Cmux Swift Package Boundaries

Explanation

PASS. The pull request changes only web/services/observability/report.ts (+31/-15). It introduces no Swift files, SwiftPM manifests, or app-target Swift logic. Therefore it cannot violate the Swift package boundary rule, and the rule's allowed-case analysis is not applicable.

Full details: Cmux Swiftpm Lockfiles

Explanation

PASS: The pull request changes only web/services/observability/report.ts (31 additions, 15 deletions). The diff contains no Package.swift, Package.resolved, .gitignore, workflow, or Xcode project changes. The SwiftPM lockfile policy is therefore not applicable.

Full details: Cmux Swift Logging

Explanation

PASS: The pull request changes only web/services/observability/report.ts; the commit diff contains no Swift files or Swift runtime code. The custom check applies only to logging introduced or materially changed in production Swift code, so it is not applicable. The changed console.error call is TypeScript and does not trigger the Swift-specific conditions.

Full details: Cmux User-Facing Error Privacy

Explanation

PASS: The pull request changes only web/services/observability/report.ts. The diff changes Sentry scheduling and flushing, plus developer-only comments. It does not add or change user-facing errors, alerts, command output, API error bodies, or recovery copy. The existing console.error("cmux.observability.error", ...) call and its scrubbing logic are unchanged. Sentry and provider references remain internal telemetry or comments, which the policy allows.

Full details: Cmux Full Internationalization

Explanation

PASS. The commit changes only web/services/observability/report.ts. It adds Sentry scheduling and flushing, plus operational comments; it does not add or change user-facing UI text, API response copy, metadata, rendered markdown, changelog content, Swift text, or localization catalogs. The existing console.error output and caller error messages are unchanged. Therefore the full-internationalization failure conditions do not apply.

Full details: Cmux Swiftui State Layout

Explanation

PASS: The pull request changes only web/services/observability/report.ts, a TypeScript file. The diff introduces no SwiftUI view, state, layout measurement, list-row store reference, or render-time state mutation. The SwiftUI state-layout check is therefore not applicable.

Full details: Cmux Architecture Rethink

Explanation

PASS: The pull request changes only web/services/observability/report.ts, a TypeScript file. The commit diff contains no Swift, SwiftUI, AppKit, or Xcode-project paths. Therefore the Swift-specific architectural failure conditions do not apply, even though the implementation uses Next.js after() for request deferral.

Full details: Cmux Swift Auxiliary Window Close Shortcuts

Explanation

PASS: The pull request changes only web/services/observability/report.ts (+31/-15). The diff contains no Swift files and no NSWindow, NSPanel, NSWindowController, Window, or WindowGroup changes. The auxiliary-window close-shortcut rule is therefore inapplicable. scripts/lint_auxiliary_window_close_shortcuts.py is not relevant to this diff.

Full details: Cmux Source Artifacts

Explanation

The diff changes only web/services/observability/report.ts. This is a hand-written application source file that adds Sentry reporting behavior. No local output, generated logs, screenshots, recordings, temp or cache directories, dependency checkouts, build output, or broad artifact directories appear in the diff.

Full details: Cmux No Test Or Debug Seam In Production Source

Explanation

PASS — the custom check applies only to changed Swift files under production Sources/ paths. The pull-request diff contains one changed file, web/services/observability/report.ts, and contains no changed production Swift paths. Therefore, it cannot introduce a Swift test or debug seam.

Full details: Cmux No Ambient Global State

Explanation

PASS: The ambient-global-state policy applies to production Swift code. The pull-request diff contains exactly one changed file, web/services/observability/report.ts, and no .swift paths. Therefore, the Swift-specific failure conditions do not apply.

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-report-error-flush

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@lawrencecchen
lawrencecchen merged commit 2f95b87 into main Aug 27, 2026
6 of 7 checks passed
@lawrencecchen
lawrencecchen deleted the feat-report-error-flush branch August 27, 2026 12:22
rustybret pushed a commit to rustybret/bmux that referenced this pull request Aug 27, 2026
87f3197 Integrate Escape passthrough fix from PR manaflow-ai#9810 (manaflow-ai#10959)
aa8ca45 refactor(tui): share draw and paint render path (manaflow-ai#10970)
2f95b87 observability: flush Sentry after the response, or events never leave the lambda (manaflow-ai#10972)
lawrencecchen added a commit that referenced this pull request Aug 27, 2026
* docs(tui): refresh intent and debt boards through 10962

* docs(tui): correct board snapshot metadata

* docs(tui): advance boards through 10970

* docs(tui): align live board snapshot and merge ledger

* docs(tui): record escape passthrough merge

* docs(tui): record merged Sentry flush change

* docs(tui): record alternate-screen wheel audit
rustybret pushed a commit to rustybret/bmux that referenced this pull request Aug 27, 2026
31a7448 cmux-tui: re-land bounded relay lifecycle hardening
d5ad6eb fix(tui): handle bounded response send errors
95abf7a docs(tui): refresh intent and debt boards through manaflow-ai#10972 (manaflow-ai#10971)
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