@@ -76,8 +76,14 @@ const MAX_CAUSE_DEPTH = 8
7676/**
7777 * HTTP status carried by a thrown value, walking the `.cause` chain so a status
7878 * set deep in a tool survives the block-level wrapping that rebuilds the error.
79- * Reads `HttpError.statusCode` (the canonical class-based carrier) plus the
80- * legacy duck-typed `statusCode`/`status` fields some paths still set.
79+ *
80+ * Reads only SIM-OWNED carriers: `HttpError.statusCode` (canonical) and the
81+ * `statusCode` field `generic-handler` re-attaches from a failed `ToolResponse`.
82+ * Deliberately does NOT read the duck-typed `status` field: that carries an
83+ * UPSTREAM target's status (`api-handler` copies it off the remote response, and
84+ * transformed HTTP tool errors carry it too). Adopting it would turn a remote
85+ * 404 into the workflow API's 404, colliding with the statuses that route owns
86+ * (404 = workflow not found, 401 = bad API key, 429 = Sim rate limit).
8187 */
8288export function readStatusCode ( value : unknown ) : number | undefined {
8389 const seen = new Set < unknown > ( )
@@ -89,9 +95,8 @@ export function readStatusCode(value: unknown): number | undefined {
8995
9096 if ( current instanceof HttpError ) return current . statusCode
9197
92- const candidate = current as unknown as { statusCode ?: unknown ; status ?: unknown }
98+ const candidate = current as unknown as { statusCode ?: unknown }
9399 if ( typeof candidate . statusCode === 'number' ) return candidate . statusCode
94- if ( typeof candidate . status === 'number' ) return candidate . status
95100
96101 current = current . cause
97102 }
0 commit comments