{"record":{"id":"f42a1cdb53eefbee","repo":"CopilotKit/CopilotKit","slug":"copilotkit-tool-arguments-parsed-to-non-object","errorCode":null,"errorMessage":"[CopilotKit] Tool arguments parsed to non-object (${typeof parsed}), falling back to empty object","messagePattern":"\\[CopilotKit\\] Tool arguments parsed to non-object \\((.+?)\\), falling back to empty object","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/runtime-client-gql/src/client/conversion.ts","lineNumber":252,"sourceCode":"          status: item.status || { code: MessageStatusCode.Success },\n        }),\n      );\n    }\n  }\n  return result;\n}\n\nfunction getPartialArguments(args: string[]) {\n  try {\n    if (!args.length) return {};\n\n    const parsed = JSON.parse(untruncateJson(args.join(\"\")));\n    if (\n      typeof parsed !== \"object\" ||\n      parsed === null ||\n      Array.isArray(parsed)\n    ) {\n      console.warn(\n        `[CopilotKit] Tool arguments parsed to non-object (${typeof parsed}), falling back to empty object`,\n      );\n      return {};\n    }\n    return parsed;\n  } catch (e) {\n    // Incomplete JSON is expected during streaming — no warning needed\n    return {};\n  }\n}\n","sourceCodeStart":234,"sourceCodeEnd":263,"githubUrl":"https://github.com/CopilotKit/CopilotKit/blob/68fbe97d87420bd84e8196965c71bd6e394a3f7a/packages/runtime-client-gql/src/client/conversion.ts#L234-L263","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// agent tool definition (before): arguments emitted as a bare string\n// after: force object-shaped arguments\nconst tool = {\n  name: \"echo\",\n  parameters: { type: \"object\", properties: { text: { type: \"string\" } }, required: [\"text\"] },\n};","handlingStrategy":"validation","validationCode":"function isPlainObject(v: unknown): v is Record<string, unknown> {\n  return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}","typeGuard":"const isPlainObject = (v: unknown): v is Record<string, unknown> =>\n  typeof v === \"object\" && v !== null && !Array.isArray(v);","tryCatchPattern":null,"preventionTips":["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"],"tags":["tool-arguments","json-parse","streaming","agui"],"backgroundTag":"malformed-tool-call-arguments","analyzedSha":"68fbe97d87420bd84e8196965c71bd6e394a3f7a","analyzedAt":"2026-08-27T04:03:26.537Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}