fix: stop reporting handled jobs-fetch failures as errors - #14507
fix: stop reporting handled jobs-fetch failures as errors#14507mattmillerai wants to merge 2 commits into
Conversation
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 10 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
Comment |
🎭 Playwright: ✅ 1780 passed, 0 failed · 1 flaky📊 Browser Reports
🎨 Storybook: ✅ Built — View Storybook📦 Bundle: 8.19 MB gzip 🔴 +889 BDetailsSummary
Category Glance App Entry Points — 3.62 kB (baseline 3.62 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 1.29 MB (baseline 1.29 MB) • 🔴 +3 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed / 1 unchanged Views & Navigation — 111 kB (baseline 111 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 12 added / 12 removed / 4 unchanged Panels & Settings — 551 kB (baseline 551 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 11 added / 11 removed / 15 unchanged User & Accounts — 28.7 kB (baseline 28.7 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 7 added / 7 removed / 3 unchanged Editors & Dialogs — 124 kB (baseline 124 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 6 added / 6 removed / 1 unchanged UI Components — 70 kB (baseline 70 kB) • ⚪ 0 BReusable component library chunks
Status: 6 added / 6 removed / 9 unchanged Data & Services — 3.45 MB (baseline 3.44 MB) • 🔴 +1.73 kBStores, services, APIs, and repositories
Status: 14 added / 14 removed / 3 unchanged Utilities & Hooks — 386 kB (baseline 386 kB) • 🟢 -1 BHelpers, composables, and utility bundles
Status: 16 added / 16 removed / 20 unchanged Vendor & Third-Party — 15.7 MB (baseline 15.7 MB) • ⚪ 0 BExternal libraries and shared vendor chunks Status: 16 unchanged Other — 12.7 MB (baseline 12.7 MB) • ⚪ 0 BBundles that do not match a named category
Status: 70 added / 70 removed / 210 unchanged ⚡ Performance Report
Show regressions
All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-07-31T21:41:49.469Z",
"gitSha": "bd3a122423887d4889c34145c8b776f559bbbb44",
"branch": "matt/fe-1466-jobs-fetch-error-noise",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2161.9210000000066,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.774000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 602.152,
"heapDeltaBytes": 5257292,
"heapUsedBytes": 73186888,
"domNodes": 16,
"jsHeapTotalBytes": 20049920,
"scriptDurationMs": 18.258,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-idle",
"durationMs": 2028.7080000000515,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.805,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 494.28,
"heapDeltaBytes": 4885608,
"heapUsedBytes": 72837312,
"domNodes": 16,
"jsHeapTotalBytes": 20312064,
"scriptDurationMs": 20.316000000000003,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1923.101000000031,
"styleRecalcs": 77,
"styleRecalcDurationMs": 46.32,
"layouts": 12,
"layoutDurationMs": 3.8019999999999996,
"taskDurationMs": 942.0580000000001,
"heapDeltaBytes": -16132060,
"heapUsedBytes": 51857252,
"domNodes": -279,
"jsHeapTotalBytes": 20176896,
"scriptDurationMs": 129.484,
"eventListeners": -146,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1878.6779999999226,
"styleRecalcs": 75,
"styleRecalcDurationMs": 40.908,
"layouts": 12,
"layoutDurationMs": 3.444,
"taskDurationMs": 952.5360000000001,
"heapDeltaBytes": -16066272,
"heapUsedBytes": 51825728,
"domNodes": -278,
"jsHeapTotalBytes": 21487616,
"scriptDurationMs": 137.578,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1738.8479999999618,
"styleRecalcs": 31,
"styleRecalcDurationMs": 16.679,
"layouts": 6,
"layoutDurationMs": 0.629,
"taskDurationMs": 389.495,
"heapDeltaBytes": 7972992,
"heapUsedBytes": 75777440,
"domNodes": 77,
"jsHeapTotalBytes": 20312064,
"scriptDurationMs": 20.145999999999997,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1676.9460000000436,
"styleRecalcs": 31,
"styleRecalcDurationMs": 16.386,
"layouts": 6,
"layoutDurationMs": 0.5369999999999999,
"taskDurationMs": 370.601,
"heapDeltaBytes": 7959096,
"heapUsedBytes": 75773724,
"domNodes": 78,
"jsHeapTotalBytes": 20312064,
"scriptDurationMs": 18.041,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "dom-widget-clipping",
"durationMs": 594.064000000003,
"styleRecalcs": 11,
"styleRecalcDurationMs": 7.782000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 386.255,
"heapDeltaBytes": -11485200,
"heapUsedBytes": 56178848,
"domNodes": 18,
"jsHeapTotalBytes": 21622784,
"scriptDurationMs": 62.114000000000004,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "dom-widget-clipping",
"durationMs": 625.5400000000009,
"styleRecalcs": 13,
"styleRecalcDurationMs": 9.933,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 401.519,
"heapDeltaBytes": -11694584,
"heapUsedBytes": 56304956,
"domNodes": 22,
"jsHeapTotalBytes": 21622784,
"scriptDurationMs": 61.318999999999996,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2044.132999999988,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.407,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 750.0009999999999,
"heapDeltaBytes": 8139700,
"heapUsedBytes": 67374708,
"domNodes": -283,
"jsHeapTotalBytes": 5042176,
"scriptDurationMs": 124.313,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2042.6009999999906,
"styleRecalcs": 9,
"styleRecalcDurationMs": 9.169999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 738.337,
"heapDeltaBytes": 7700872,
"heapUsedBytes": 66399960,
"domNodes": -280,
"jsHeapTotalBytes": 3993600,
"scriptDurationMs": 120.076,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2228.9670000000115,
"styleRecalcs": 69,
"styleRecalcDurationMs": 13.736000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1341.2640000000001,
"heapDeltaBytes": 6333708,
"heapUsedBytes": 66194312,
"domNodes": -282,
"jsHeapTotalBytes": 5005312,
"scriptDurationMs": 449.99100000000004,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2193.4289999999237,
"styleRecalcs": 69,
"styleRecalcDurationMs": 14.498000000000005,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1348.761,
"heapDeltaBytes": 7136868,
"heapUsedBytes": 67717868,
"domNodes": -283,
"jsHeapTotalBytes": 4743168,
"scriptDurationMs": 449.30400000000003,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3315.19899999995,
"styleRecalcs": 64,
"styleRecalcDurationMs": 19.474,
"layouts": 60,
"layoutDurationMs": 7.711,
"taskDurationMs": 1594.468,
"heapDeltaBytes": 3856148,
"heapUsedBytes": 65390564,
"domNodes": -289,
"jsHeapTotalBytes": 7925760,
"scriptDurationMs": 548.964,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-zoom",
"durationMs": 3232.6170000000047,
"styleRecalcs": 63,
"styleRecalcDurationMs": 12.835999999999997,
"layouts": 60,
"layoutDurationMs": 7.433000000000001,
"taskDurationMs": 1588.072,
"heapDeltaBytes": -548872,
"heapUsedBytes": 61588984,
"domNodes": -288,
"jsHeapTotalBytes": 8450048,
"scriptDurationMs": 549.3520000000001,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "minimap-idle",
"durationMs": 2066.49299999998,
"styleRecalcs": 8,
"styleRecalcDurationMs": 8.396,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 743.1940000000002,
"heapDeltaBytes": 8397148,
"heapUsedBytes": 68900920,
"domNodes": -283,
"jsHeapTotalBytes": 3731456,
"scriptDurationMs": 121.30300000000003,
"eventListeners": -146,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "minimap-idle",
"durationMs": 2037.898000000041,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.819999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 741.8169999999999,
"heapDeltaBytes": 8486324,
"heapUsedBytes": 69208984,
"domNodes": -284,
"jsHeapTotalBytes": 5042176,
"scriptDurationMs": 120.688,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 662.2560000000135,
"styleRecalcs": 47,
"styleRecalcDurationMs": 14.842,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 456,
"heapDeltaBytes": -12057980,
"heapUsedBytes": 55963772,
"domNodes": 20,
"jsHeapTotalBytes": 21884928,
"scriptDurationMs": 128.248,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 610.4709999999614,
"styleRecalcs": 46,
"styleRecalcDurationMs": 10.257,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 414.531,
"heapDeltaBytes": -11494944,
"heapUsedBytes": 56578920,
"domNodes": 18,
"jsHeapTotalBytes": 22147072,
"scriptDurationMs": 123.389,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2005.2840000000174,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.451,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 462.45000000000005,
"heapDeltaBytes": 4322980,
"heapUsedBytes": 72395280,
"domNodes": 20,
"jsHeapTotalBytes": 20836352,
"scriptDurationMs": 14.946,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2013.9840000000504,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.796,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 512.143,
"heapDeltaBytes": -21674764,
"heapUsedBytes": 46222796,
"domNodes": 20,
"jsHeapTotalBytes": 20439040,
"scriptDurationMs": 15.525,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1759.034999999983,
"styleRecalcs": 77,
"styleRecalcDurationMs": 38.492,
"layouts": 16,
"layoutDurationMs": 4.849,
"taskDurationMs": 821.22,
"heapDeltaBytes": -4289972,
"heapUsedBytes": 63408044,
"domNodes": 63,
"jsHeapTotalBytes": 20836352,
"scriptDurationMs": 104.003,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1722.8289999999333,
"styleRecalcs": 76,
"styleRecalcDurationMs": 38.64,
"layouts": 16,
"layoutDurationMs": 4.681,
"taskDurationMs": 781.735,
"heapDeltaBytes": -4591428,
"heapUsedBytes": 63482880,
"domNodes": 63,
"jsHeapTotalBytes": 21098496,
"scriptDurationMs": 94.774,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-transition-enter",
"durationMs": 1399.8559999999998,
"styleRecalcs": 18,
"styleRecalcDurationMs": 30.32399999999999,
"layouts": 14,
"layoutDurationMs": 12.473,
"taskDurationMs": 939.8329999999997,
"heapDeltaBytes": 30990008,
"heapUsedBytes": 97990396,
"domNodes": 13673,
"jsHeapTotalBytes": 15990784,
"scriptDurationMs": 35.346000000000004,
"eventListeners": 2371,
"totalBlockingTimeMs": 131,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "viewport-pan-sweep",
"durationMs": 8661.821999999973,
"styleRecalcs": 249,
"styleRecalcDurationMs": 37.967,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4859.789,
"heapDeltaBytes": 12464204,
"heapUsedBytes": 71496856,
"domNodes": -282,
"jsHeapTotalBytes": 8118272,
"scriptDurationMs": 1533.4270000000001,
"eventListeners": -128,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8450.449999999932,
"styleRecalcs": 250,
"styleRecalcDurationMs": 38.92999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4760.796,
"heapDeltaBytes": 11082516,
"heapUsedBytes": 70203024,
"domNodes": -280,
"jsHeapTotalBytes": 7331840,
"scriptDurationMs": 1452.871,
"eventListeners": -126,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 17466.501999999993,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 17421.984,
"heapDeltaBytes": -35219216,
"heapUsedBytes": 167791724,
"domNodes": -8312,
"jsHeapTotalBytes": -14360576,
"scriptDurationMs": 601.1229999999999,
"eventListeners": -16389,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.780000000000047,
"p95FrameDurationMs": 16.80000000000291
},
{
"name": "vue-large-graph-idle",
"durationMs": 17496.64100000007,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 17442.317,
"heapDeltaBytes": -33904656,
"heapUsedBytes": 179333348,
"domNodes": -8312,
"jsHeapTotalBytes": -10391552,
"scriptDurationMs": 604.138,
"eventListeners": -16389,
"totalBlockingTimeMs": 0,
"frameDurationMs": 18.333333333333332,
"p95FrameDurationMs": 16.80000000000291
},
{
"name": "vue-large-graph-pan",
"durationMs": 21074.430000000008,
"styleRecalcs": 141,
"styleRecalcDurationMs": 21.158999999999985,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 21010.597999999998,
"heapDeltaBytes": -66541464,
"heapUsedBytes": 153919436,
"domNodes": -8312,
"jsHeapTotalBytes": -14094336,
"scriptDurationMs": 965.2719999999999,
"eventListeners": -16381,
"totalBlockingTimeMs": 207,
"frameDurationMs": 17.780000000000047,
"p95FrameDurationMs": 16.80000000000291
},
{
"name": "vue-large-graph-pan",
"durationMs": 21158.343999999943,
"styleRecalcs": 146,
"styleRecalcDurationMs": 18.967999999999986,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 21094.173,
"heapDeltaBytes": -42629176,
"heapUsedBytes": 165443996,
"domNodes": -8312,
"jsHeapTotalBytes": -15933440,
"scriptDurationMs": 900.673,
"eventListeners": -16383,
"totalBlockingTimeMs": 263,
"frameDurationMs": 17.77333333333336,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 106.83099999999968,
"styleRecalcs": 6,
"styleRecalcDurationMs": 12.636,
"layouts": 3,
"layoutDurationMs": 0.7070000000000002,
"taskDurationMs": 84.625,
"heapDeltaBytes": 3267244,
"heapUsedBytes": 70305264,
"domNodes": 115,
"jsHeapTotalBytes": 3145728,
"scriptDurationMs": 7.2730000000000015,
"eventListeners": 33,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "workflow-execution",
"durationMs": 459.98499999996056,
"styleRecalcs": 13,
"styleRecalcDurationMs": 19.413,
"layouts": 3,
"layoutDurationMs": 0.609,
"taskDurationMs": 115.761,
"heapDeltaBytes": -15998988,
"heapUsedBytes": 50932764,
"domNodes": 119,
"jsHeapTotalBytes": 7467008,
"scriptDurationMs": 9.754000000000001,
"eventListeners": 65,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.700000000000728
}
]
} |
📄 Knowledge reviewDosu skipped reviewing this PR because your organization has used its |
|
Verification note: a whole-repo |
There was a problem hiding this comment.
🔍 Cursor Review — Consolidated panel
Triggered by @mattmillerai.
Found 5 finding(s).
| Severity | Count |
|---|---|
| 🟠 High | 1 |
| 🟡 Medium | 2 |
| 🟢 Low | 2 |
Panel: 8/8 reviewers contributed findings.
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## main #14507 +/- ##
==========================================
- Coverage 79.35% 79.31% -0.04%
==========================================
Files 1767 1768 +1
Lines 113935 114034 +99
Branches 35819 36653 +834
==========================================
+ Hits 90414 90448 +34
- Misses 22978 23043 +65
Partials 543 543
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 2 files with indirect coverage changes 🚀 New features to boost your workflow:
|
Address review: a persisted `pagehide` is a back/forward-cache freeze, not a discard, so aborting there cancelled a poll on a page that keeps running and settled an empty snapshot over the queue. Re-mint the controller on `pageshow` rather than immediately after the abort, guard the listener registration for non-DOM contexts, and extend the same teardown handling to `fetchJobDetail`.
|
🤖 The reviews loop filed Linear follow-up ticket(s) for review thread(s) deferred as out of scope for this PR:
The following carry
|
christian-byrne
left a comment
There was a problem hiding this comment.
Can you reconcile this was other OPEN PRs on the repo with similar approach/intent? In general, reporting of errors should not incite us to remove the reporting but rather address the bug.
ELI-5
When the app asks the server "what jobs do I have?", that question can fail for boring reasons — you weren't signed in yet, or you closed the tab mid-question. The app already shrugged those off and kept working, but it also shouted "ERROR!" into our monitoring every time, which made real problems hard to find. Now it only shouts when something is actually wrong.
Summary
The jobs poll already degrades gracefully — on a non-OK status or a thrown fetch it returns an empty result set and the UI carries on — but it logged both paths with
console.error, so every handled failure was recorded as an error session in RUM. Failures that are ordinary lifecycle events no longer report; genuine faults still do.Changes
fetchJobsRawnow classifies its failures instead of treating them all as errors. A401logs atwarn. A request cancelled because the page is going away is not logged at all. A403, a5xx, a body that fails schema validation, and a real network fault all still log atconsole.error. Every path returns the same empty result set as before, so callers and the UI are unchanged.AbortSignal(src/utils/pageTeardownUtil.ts) is aborted when the page is discarded and passed with the jobs request, so a teardown cancellation is recognisable viasignal.abortedeven when the browser surfaces it as a bareTypeError: Failed to fetch. ExplicitAbortErrorrejections are recognised too.fetchJobDetailgets the same treatment.pagehide.pagehiderather thanbeforeunloadbecausebeforeunloadalso fires for navigations the user then cancels; and persisted-only-excluded because a persistedpagehideis a back/forward-cache freeze, not a discard — the page resumes, and cancelling its poll would settle an empty snapshot over the queue, which in turn stops polling (useQueuePollingonly schedules whileactiveJobsCount === 1). The controller is re-minted onpageshow, so a browser that reports a discard for a page it later restores is not left with a spent signal.If teardown somehow cancels a request before
pagehidefires, the failure is still reported — the fallback direction is "noisier", never "silently swallowed".Review Focus
Why the 401 is not gated, despite being the obvious fix. The request seam these fetchers are injected with already waits for auth to resolve before every cloud request (
waitForAuthInitializationinsrc/scripts/api.ts, awaited at the top offetchApi), and a401response is already retried once behind a token re-mint (fetchWithUnifiedRemint). So the ordering gate the ticket proposed exists; adding a second one in the jobs layer would duplicate it. What still reaches this code is a poll that outran its session — an unauthenticated or expired session, or the 10s auth-initialisation timeout elapsing — which is a lifecycle state, not a defect. Hencewarnrather than a new gate. The residual timeout case already logs its own warning where it happens.The 403 is deliberately still an error. Reading the server side, a
403on this endpoint is not raised by the jobs handler at all — it comes from shared request-authorisation middleware, which returns403for several unrelated reasons (the credential type not being accepted for the route, an authorisation predicate failing for the account, and an account scheduled for deletion). At least one of those is an expected terminal state and at least one would be a real bug, so the ~79 sessions are almost certainly a mix. The frontend cannot currently separate them because it logs only the status code and discards the response body, which carries a machine-readable error type. Keeping403atconsole.errorpreserves that signal rather than hiding a possible authorisation bug behind this cleanup. Follow-up worth filing separately: surface the response's error type alongside the status so the cluster can be split, then decide whether anything is a real defect. Deliberately not widened here — the server side is out of scope for this change.Scope calls. An aborted fetch still returns the same empty result set rather than rethrowing, so callers cannot distinguish "no jobs" from "cancelled". Raised in review; not changed here. With the abort now restricted to a genuine discard the surviving-page case is gone, and rethrowing is a change to the fetch contract that cascades into
api.getQueue/api.getHistory,queueStore,assetsStoreandmissingMediaAssetResolver— each needing its own abort guard at the log site or it re-introduces the noise this PR removes. Filed as a follow-up. The otherTypeError: Failed to fetchsites (remote config, the bare fetch wrapper) are the same pattern at different call sites and are out of scope here;src/utils/pageTeardownUtil.tsis written so they can reuse it.Verification
vue-tsc --noEmit(whole repo),oxlint --type-aware,eslint(0 errors) andoxfmtall clean.vitest runoversrc/platform/remote/comfyui/jobs,src/platform/workflow/cloud/getWorkflowFromHistory.test.ts,src/platform/missingMedia,src/platform/assets,src/composables/queue,src/stores/queueStore.test.ts,src/services/jobOutputCache.test.tsandsrc/utils: 106 files / 1752 tests passing. New unit tests cover the abort path, the page-discard path (list and detail), the frozen-page path (asserting the signal is not aborted and the failure still reports), the restored-page path, the401, a5xx, a real network error, and a malformed body — each asserting which of them report.The RUM numbers below are as reported on the dashboard; they were not re-queried while making this change.
Provenance
This came out of a goal run against the Cloud frontend error-free sessions Datadog dashboard ("State of Dog"), RUM app
Comfy Cloud Frontend, envprod-v2, measured over a rolling 7-day window ending 2026-07-31. Baseline: error-free sessions 17–22% daily, 8,662 of 10,790 sessions containing at least one error; target ≥90% daily. The three clusters this addresses —TypeError: Failed to fetch(554 sessions),401(113),403(79) — are 746 sessions/week combined, about 18% of the residual error sessions once the extension-loading 404 cluster is excluded. The first two stop reporting; the third is left reporting on purpose, per above.