CopilotKit/CopilotKit · warning
[CopilotKit] Tool arguments parsed to non-object (${typeof p
Error message
[CopilotKit] Tool arguments parsed to non-object (${typeof parsed}), falling back to empty object What it means
While streaming agent output, CopilotKit accumulates tool-call argument fragments and parses them with JSON.parse once complete. If the parsed value is not a plain object (e.g. the model emitted a bare string, number, boolean, or array as arguments), the runtime client warns and substitutes an empty object so downstream rendering does not crash. The message includes the actual typeof the parsed value.
Source
Thrown at packages/runtime-client-gql/src/client/conversion.ts:252
status: item.status || { code: MessageStatusCode.Success },
}),
);
}
}
return result;
}
function getPartialArguments(args: string[]) {
try {
if (!args.length) return {};
const parsed = JSON.parse(untruncateJson(args.join("")));
if (
typeof parsed !== "object" ||
parsed === null ||
Array.isArray(parsed)
) {
console.warn(
`[CopilotKit] Tool arguments parsed to non-object (${typeof parsed}), falling back to empty object`,
);
return {};
}
return parsed;
} catch (e) {
// Incomplete JSON is expected during streaming — no warning needed
return {};
}
}
View on GitHub (pinned to 68fbe97d87)
Solutions
- Inspect the logged typeof to see what the model actually sent; if arguments are intentionally scalar, wrap them in an object on the agent side (e.g. {value: ...})
- Improve the tool's parameter schema/definitions so the model emits an object; ensure the tool handler tolerates an empty {} fallback
- If it happens only mid-stream, treat it as transient partial-JSON noise and ignore the warning; only act on the final message
- Switch to a stronger model if malformed arguments recur
Example fix
// agent tool definition (before): arguments emitted as a bare string
// after: force object-shaped arguments
const tool = {
name: "echo",
parameters: { type: "object", properties: { text: { type: "string" } }, required: ["text"] },
}; Defensive patterns
Strategy: validation
Validate before calling
function isPlainObject(v: unknown): v is Record<string, unknown> {
return typeof v === "object" && v !== null && !Array.isArray(v);
} Type guard
const isPlainObject = (v: unknown): v is Record<string, unknown> => typeof v === "object" && v !== null && !Array.isArray(v);
Prevention
- Define explicit JSON Schema (type: 'object') on every tool
- Validate required tool arguments in the handler before acting
- Log raw streamed argument strings when diagnosing model output
When it happens
Trigger: An LLM streams tool arguments that parse to a JSON scalar or array, e.g. '"hello world"', '42', 'true', or '[1,2,3]' inside a streaming tool call handled by convertGqlOutputToMessages -> getPartialArguments. Also occurs when untruncation of a partially-streamed JSON produces a non-object like an empty string.
Common situations: Weak models or low temperature misconfiguration producing malformed tool arguments; custom agents (LangGraph/CrewAI) that return non-object argument payloads; partially streamed JSON at message boundaries being untruncated to a scalar.
Related errors
- [CopilotKit] Failed to parse tool arguments, falling back to
- [CopilotKit] Tool arguments parsed to non-object (${typeof a
- [CopilotKit] Failed to parse tool arguments, falling back to
- AI SDK tool-approval-request is missing toolCallId
- AI SDK stream error: ${JSON.stringify(p)}
AI-assisted analysis of CopilotKit/CopilotKit@68fbe97d87 (2026-08-27).
Data as JSON: /api/errors/f42a1cdb53eefbee.
Report an issue: GitHub.