Skip to content

Commit 8f74771

Browse files
rustyconoverclaude
andcommitted
dispatch: propagate field-name/count mismatch as RpcError
Conform-failure was being silently swallowed for both transports after 61025e1/589a95f, which let exchange handlers run on a wrong-shape input batch. For column-name/count mismatches the handler then either picked up the wrong column by index or hung the client (the conformance test TestExchangeCastCompatible::test_cast_incompatible_column_name[pipe] deadlocked end-to-end and tripped the 90s CI step timeout). Tighten the catch in both src/dispatch/stream.ts and src/http/dispatch.ts: TypeError (the only failure mode for field name/count mismatch in conformBatchToSchema) is rethrown so callers see a structured RpcError. Other conform failures (numeric cast issues for dynamic-input handlers) still fall through with the original batch; handlers that genuinely bind their input shape per call should set state.__inputSchema so the conform check is bypassed entirely. Local: 127/127 unit + 898/898 conformance pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 594f742 commit 8f74771

2 files changed

Lines changed: 11 additions & 0 deletions

File tree

src/dispatch/stream.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ export async function dispatchStream(
138138
try {
139139
inputBatch = conformBatchToSchema(inputBatch, expectedInputSchema);
140140
} catch (e) {
141+
// Field name/count mismatch (TypeError) is a hard contract violation —
142+
// propagate as an RpcError so callers see a structured failure instead
143+
// of a downstream hang or silent garbage. Other conform failures (e.g.
144+
// type-cast issues for dynamic-input handlers) fall through with the
145+
// original batch — handlers that bind their input shape per-call
146+
// should set state.__inputSchema so the conform doesn't run at all.
147+
if (e instanceof TypeError) throw e;
141148
console.debug?.(`Schema conformance skipped: ${e instanceof Error ? e.message : e}`);
142149
}
143150
}

src/http/dispatch.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ export async function httpDispatchStreamExchange(
277277
try {
278278
conformedBatch = conformBatchToSchema(reqBatch, inputSchema);
279279
} catch (e) {
280+
// Field name/count mismatch is a hard contract violation — surface it
281+
// as an error rather than letting handlers see a wrong-shape batch
282+
// (mirrors the subprocess dispatch in src/dispatch/stream.ts).
283+
if (e instanceof TypeError) throw e;
280284
console.debug?.(`Schema conformance skipped: ${e instanceof Error ? e.message : e}`);
281285
}
282286
}

0 commit comments

Comments
 (0)