When a tool result is too large to fit in a subc frame, the frame build fails and the error is logged. Nothing is sent back. The agent's tool call sits unanswered until some external timeout.
// crates/aft/src/subc/mod.rs:4438
Err(error) => {
log::error!("subc attach: failed to build tool response frame: {error}");
}
That's the whole error arm — no fallback frame, no truncation, no error surfaced to the caller. Compare the arm directly above it, which at least logs a warning and is on a path where the frame was built successfully.
The limit it trips:
// subc-protocol frame.rs:47
if body.len() > MAX_FRAME_BODY_LEN as usize {
return Err(FrameBuildError::BodyTooLarge ...)
}
// subc-protocol lib.rs:119
pub const MAX_FRAME_BODY_LEN: u32 = 64 * 1024 * 1024;
build_tool_response_frame (wire.rs:495) serializes the full ToolCallResult with no size guard of its own, so the protocol-level check is the only one.
The effective limit is about half of 64 MiB. For first-party (trusted) binds the envelope carries the rendered text twice — once as text, once inside structuredContent — which the code comments at wire.rs:418-419 acknowledge. So a single payload of ~32 MiB of real content is enough to trip it.
What reaches that size: a read of a large file, a broad grep/search with many hits, an outline over a large directory, or a big gather context pack. None of these are exotic — they're the tools most likely to produce a large result, and the failure mode is silent.
Severity: P2. It needs a large payload to trigger, but when it does the agent gets no error to act on — it just hangs, which is worse than a clear failure. An agent that receives "response too large" can retry with a narrower scope; an agent that receives nothing can't do anything.
Fix direction: on BodyTooLarge, send a small error frame back on the same correlation id — or truncate the text with an explicit marker and set a complete: false-style field, which would fit the honest-reporting convention in protocol.rs better than dropping. Either beats silence.
Provenance and limits. Found in a parallel read-only sweep; I verified the error arm at mod.rs:4434-4441 firsthand before filing. I have not reproduced the hang — no forced 64 MiB payload, no timing measurement. The claim is that the code path exists and has no reply on it, which is checkable by reading; whether it fires in practice depends on payload sizes I haven't sampled. Line numbers against 28930e09.
When a tool result is too large to fit in a subc frame, the frame build fails and the error is logged. Nothing is sent back. The agent's tool call sits unanswered until some external timeout.
That's the whole error arm — no fallback frame, no truncation, no error surfaced to the caller. Compare the arm directly above it, which at least logs a warning and is on a path where the frame was built successfully.
The limit it trips:
build_tool_response_frame(wire.rs:495) serializes the fullToolCallResultwith no size guard of its own, so the protocol-level check is the only one.The effective limit is about half of 64 MiB. For first-party (trusted) binds the envelope carries the rendered text twice — once as text, once inside
structuredContent— which the code comments atwire.rs:418-419acknowledge. So a single payload of ~32 MiB of real content is enough to trip it.What reaches that size: a
readof a large file, a broadgrep/searchwith many hits, anoutlineover a large directory, or a biggathercontext pack. None of these are exotic — they're the tools most likely to produce a large result, and the failure mode is silent.Severity: P2. It needs a large payload to trigger, but when it does the agent gets no error to act on — it just hangs, which is worse than a clear failure. An agent that receives "response too large" can retry with a narrower scope; an agent that receives nothing can't do anything.
Fix direction: on
BodyTooLarge, send a small error frame back on the same correlation id — or truncate the text with an explicit marker and set acomplete: false-style field, which would fit the honest-reporting convention inprotocol.rsbetter than dropping. Either beats silence.Provenance and limits. Found in a parallel read-only sweep; I verified the error arm at
mod.rs:4434-4441firsthand before filing. I have not reproduced the hang — no forced 64 MiB payload, no timing measurement. The claim is that the code path exists and has no reply on it, which is checkable by reading; whether it fires in practice depends on payload sizes I haven't sampled. Line numbers against28930e09.