decolua/9router · error
Kiro toolUseEvent is missing a tool name
Error message
Kiro toolUseEvent is missing a tool name
What it means
Within a toolUseEvent fragment the executor derives the tool name and requires a non-empty string after trimming. A missing or empty 'name' makes the tool call unidentifiable — the executor cannot construct a function_call for the client — so it throws. This surfaces upstream protocol violations immediately instead of emitting an anonymous tool call.
Source
Thrown at open-sse/executors/kiro.js:832
} else if (eventType === "reasoningContentEvent") {
const value = event.payload?.reasoningContentEvent || event.payload || {};
const content = typeof value === "string" ? value : value.text || value.content || "";
if (content) {
state.hasReasoning = true;
state.totalContentLength += content.length;
emitDelta(controller, { reasoning_content: content });
}
} else if (eventType === "codeEvent" && typeof event.payload?.content === "string") {
state.hasCode = true;
state.totalContentLength += event.payload.content.length;
emitDelta(controller, { content: event.payload.content });
} else if (eventType === "toolUseEvent") {
state.sawToolUse = true;
const values = Array.isArray(event.payload) ? event.payload : [event.payload];
if (!values[0]) throw new Error("Kiro toolUseEvent is empty");
for (const value of values) {
const name = typeof value?.name === "string" ? value.name.trim() : "";
if (!name) throw new Error("Kiro toolUseEvent is missing a tool name");
let id;
if (value.toolUseId == null) {
id = `call_${created}_${state.tools.size + 1}`;
} else if (typeof value.toolUseId !== "string" || !value.toolUseId.trim()) {
throw new Error("Kiro toolUseEvent has an invalid toolUseId");
} else {
id = value.toolUseId;
}
let tool = state.tools.get(id);
if (!tool) {
tool = { id, name };
state.tools.set(id, tool);
state.bufferedToolBytes += encoder.encode(id).byteLength + encoder.encode(name).byteLength + 32;
assertToolBufferBound();
} else if (tool.name !== name) {
throw new Error("Kiro tool name changed between fragments");
}
appendToolInput(tool, value.input);View on GitHub (pinned to 90b52e06ff)
Solutions
- Retry the request once — this is often a transient malformed fragment from the upstream
- Check the installed Kiro upstream API contract for a renamed/moved name field and update the executor's field extraction
- Log the full toolUseEvent payload on this path to confirm the actual shape being received
- If only the input-fragment frames lack name (name sent on first frame only), make the executor carry-forward the name for known toolUseId instead of throwing
Example fix
// before: strict per-fragment name requirement
const name = typeof value?.name === 'string' ? value.name.trim() : '';
if (!name) throw new Error('Kiro toolUseEvent is missing a tool name');
// after: fall back to name already recorded for this toolUseId (continuation fragments)
let name = typeof value?.name === 'string' ? value.name.trim() : '';
if (!name && value?.toolUseId) name = state.tools.get(value.toolUseId)?.name || '';
if (!name) throw new Error('Kiro toolUseEvent is missing a tool name'); Defensive patterns
Strategy: try-catch
Type guard
function isNamedToolFragment(value) {
return Boolean(value) && typeof value.name === 'string' && value.name.trim().length > 0;
} Try / catch
try {
return await streamKiro(req);
} catch (e) {
if (/toolUseEvent is missing a tool name/.test(e.message)) {
logRawEventForDebug(e); // capture surrounding EventStream frames
if (attempts < 2) return retry(req);
}
throw e;
} Prevention
- Retry once on tool-name validation failures before surfacing to the client
- Log full toolUseEvent payloads on this path to detect upstream field renames quickly
- If your upstream sends name only on the first fragment, ensure the executor carry-forwards it by toolUseId
- Re-run translator/executor integration tests after any Kiro API version bump
When it happens
Trigger: A toolUseEvent value where value is null/undefined, value.name is not a string, or value.name trims to an empty string — e.g. Kiro sent a fragment carrying only input deltas before the fragment containing the name, or the name field was renamed in an upstream API update.
Common situations: Upstream API/protocol changes renaming the 'name' field; streaming implementations that split tool metadata across frames; model emitting degenerate tool calls with blank names under heavy load or near context limits.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- Kiro toolUseEvent is empty
- Kiro toolUseEvent has an invalid toolUseId
- Kiro tool name changed between fragments
- Kiro tool_use stop reason did not include a complete tool ca
- AWS EventStream frame is shorter than 16 bytes
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/0e2928745fec0d67.
Report an issue: GitHub.