Repository navigation
Commit 4f36f61
feat(core,sdk,cli,webapp,run-engine): store and show thrown error causes
## Summary
Throwing an error that wraps another one lost the inner error entirely:
```ts
throw new Error("Could not sync the customer", { cause: originalError });
```
Only the outermost name, message and stack were ever serialized, so
`originalError` never reached the dashboard, the CLI, alerts, or the
API. The cause chain is now flattened onto the run error and shown
everywhere the error itself is shown.
## Where you see it
| Surface | How it appears |
|---|---|
| Run page, error panel | A "Caused by" block per cause under the main
error, each with its own name, message and stack |
| Trace view, span exception | Appended to the exception message and
stacktrace as `Caused by: ...` |
| `dev` CLI | Appended to the printed stack as `Caused by: ...`, with
full frames |
| Failure alerts: email | A "Caused by" line plus a stack code block per
cause |
| Failure alerts: Slack | Appended to the error code block |
| Failure alerts: webhook | `causes` array on the `TaskRunError` payload
|
| REST API (`retrieve run`) | `causes` array on `run.error` |
| Realtime run records | `causes` array on `run.error` |
| MCP run tools | A `Caused by:` line per cause under the error |
| SDK, `triggerAndWait` and `triggerAndSubscribe` | Rebuilt as a native
`err.cause` chain |
Not included: the Errors page groups by fingerprint and reads flat
`error_type` / `error_message` / `sample_stack_trace` columns, so it
keeps showing the outermost error only. Surfacing causes there needs a
schema change and is left for separate work. Fingerprints are computed
from type, message and stack and do not read `causes`, so existing error
groups are unaffected by this change.
## Design
`TaskRunBuiltInError` and `SerializedError` gain an optional `causes`
array, flattened outermost first rather than nested. A cause chain is
linear, so an array models it without needing a recursive zod schema
threaded through every exhaustive switch.
Causes are arbitrary user data, so the walk is defensive throughout. It
is bounded at five links and cycle guarded, and every read is wrapped:
`instanceof`, a property get, `JSON.stringify` and `String` can each
throw on a hostile or revoked `Proxy`, and `parseError` sits on the
universal error path. Losing a cause there is acceptable; throwing would
replace the user's real error with a crash.
```ts
function readErrorCause(value: unknown): unknown {
try {
return value instanceof Error ? (value as { cause?: unknown }).cause : undefined;
} catch (_e) {
return undefined;
}
}
```
Cause stacks get a tighter frame budget than the error that was actually
thrown (10 frames vs 50), and the run engine's truncation net re-bounds
them, so the worst-case stored payload stays bounded rather than
multiplying by the chain length.
Closes #1603
Mono-RevId: 02396fcda2dcedbabaddfa63f90f91acab6f36721 parent ae86de2 commit 4f36f61
16 files changed
Lines changed: 1031 additions & 98 deletions
File tree
- .changeset
- apps/webapp/app
- components/runs/v3
- routes
- resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam
- storybook.run-error
- storybook
- v3
- eventRepository
- services/alerts
- internal-packages
- emails/emails
- run-engine/src/engine/systems
- packages
- build/src
- cli-v3/src
- dev
- mcp
- core
- src/v3
- schemas
- test
- trigger-sdk/src/v3
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
Lines changed: 2 additions & 76 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
11 | 10 | | |
12 | 11 | | |
13 | 12 | | |
14 | 13 | | |
15 | 14 | | |
16 | 15 | | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
| 16 | + | |
22 | 17 | | |
23 | 18 | | |
24 | 19 | | |
| |||
27 | 22 | | |
28 | 23 | | |
29 | 24 | | |
| 25 | + | |
30 | 26 | | |
31 | | - | |
32 | 27 | | |
33 | 28 | | |
34 | 29 | | |
| |||
1561 | 1556 | | |
1562 | 1557 | | |
1563 | 1558 | | |
1564 | | - | |
1565 | | - | |
1566 | | - | |
1567 | | - | |
1568 | | - | |
1569 | | - | |
1570 | | - | |
1571 | | - | |
1572 | | - | |
1573 | | - | |
1574 | | - | |
1575 | | - | |
1576 | | - | |
1577 | | - | |
1578 | | - | |
1579 | | - | |
1580 | | - | |
1581 | | - | |
1582 | | - | |
1583 | | - | |
1584 | | - | |
1585 | | - | |
1586 | | - | |
1587 | | - | |
1588 | | - | |
1589 | | - | |
1590 | | - | |
1591 | | - | |
1592 | | - | |
1593 | | - | |
1594 | | - | |
1595 | | - | |
1596 | | - | |
1597 | | - | |
1598 | | - | |
1599 | | - | |
1600 | | - | |
1601 | | - | |
1602 | | - | |
1603 | | - | |
1604 | | - | |
1605 | | - | |
1606 | | - | |
1607 | | - | |
1608 | | - | |
1609 | | - | |
1610 | | - | |
1611 | | - | |
1612 | | - | |
1613 | | - | |
1614 | | - | |
1615 | | - | |
1616 | | - | |
1617 | | - | |
1618 | | - | |
1619 | | - | |
1620 | | - | |
1621 | | - | |
1622 | | - | |
1623 | | - | |
1624 | | - | |
1625 | | - | |
1626 | | - | |
1627 | | - | |
1628 | | - | |
1629 | | - | |
1630 | | - | |
1631 | | - | |
1632 | | - | |
1633 | 1559 | | |
1634 | 1560 | | |
1635 | 1561 | | |
| |||
0 commit comments