{"record":{"id":"6364abadc350e213","repo":"openclaw/openclaw","slug":"codex-settled-turn-projection-requires-object-tool","errorCode":null,"errorMessage":"Codex settled-turn projection requires object tool arguments","messagePattern":"Codex settled-turn projection requires object tool arguments","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"extensions/codex/src/app-server/settled-turn-projection.ts","lineNumber":76,"sourceCode":"\nfunction requireToolName(value: unknown): string {\n  const name = readNonEmptyString(value);\n  if (!name || !TOOL_NAME_PATTERN.test(name)) {\n    throw new Error(\"Codex settled-turn projection found an invalid tool name\");\n  }\n  return name;\n}\n\nfunction serializeToolArguments(value: unknown): string {\n  if (typeof value === \"string\") {\n    let parsed: unknown;\n    try {\n      parsed = JSON.parse(value);\n    } catch {\n      throw new Error(\"Codex settled-turn projection found invalid JSON tool arguments\");\n    }\n    if (!isRecord(parsed)) {\n      throw new Error(\"Codex settled-turn projection requires object tool arguments\");\n    }\n    return requireBoundedText(value, \"tool arguments\");\n  }\n  if (!isRecord(value)) {\n    throw new Error(\"Codex settled-turn projection requires object tool arguments\");\n  }\n  let serialized: string;\n  try {\n    serialized = JSON.stringify(value);\n  } catch {\n    throw new Error(\"Codex settled-turn projection found unserializable tool arguments\");\n  }\n  return requireBoundedText(serialized, \"tool arguments\");\n}\n\nfunction projectUserMessage(message: AgentMessage): JsonValue[] {\n  const record = message as unknown as Record<string, unknown>;\n  const upstreamUserText = readUpstreamUserText(message);","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/openclaw/openclaw/blob/01804a75319da4b69c9ab98ceaa30477e22b8c0b/extensions/codex/src/app-server/settled-turn-projection.ts#L58-L94","documentation":"Thrown by serializeToolArguments when tool arguments were supplied as a string, JSON.parse succeeded, but the parsed value is not a record object (e.g. an array, number, string, boolean, or null). Codex function_call arguments must serialize to a JSON object, so a JSON string that parses to a non-object is rejected even though it is valid JSON.","triggerScenarios":"arguments is the string \"[1,2,3]\" (parses to array), \"42\" (number), \"\\\"text\\\"\" (string), \"null\", or \"true\"; a provider that stringified a non-object value as arguments.","commonSituations":"Provider adapter that stringified a positional-arguments array instead of a named-args object; a model that returned a bare scalar as arguments; test fixture using JSON.stringify on a non-object.","solutions":["Inspect the parsed value of arguments to see its actual type.","Ensure the toolCall producer builds arguments as a plain object {} and JSON.stringify it.","If the upstream legitimately uses positional args, wrap them as { args: [...] } at the adapter."],"exampleFix":"// before\n{ type: \"toolCall\", id, name, arguments: JSON.stringify([1, 2, 3]) } // parses to array -> throws\n\n// after\n{ type: \"toolCall\", id, name, arguments: JSON.stringify({ args: [1, 2, 3] }) }","handlingStrategy":"validation","validationCode":"function isJsonObjectArgumentsString(value: unknown): boolean {\n  if (typeof value !== \"string\") return false;\n  try {\n    const parsed = JSON.parse(value);\n    return typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed);\n  } catch {\n    return false;\n  }\n}\n\n// at the producer\nif (typeof args === \"string\") {\n  const parsed = JSON.parse(args);\n  if (Array.isArray(parsed) || typeof parsed !== \"object\" || parsed === null) {\n    args = JSON.stringify({ value: parsed });\n  }\n}","typeGuard":"function parsesToJsonObject(value: unknown): boolean {\n  if (typeof value !== \"string\") return false;\n  try {\n    const p = JSON.parse(value);\n    return typeof p === \"object\" && p !== null && !Array.isArray(p);\n  } catch {\n    return false;\n  }\n}","tryCatchPattern":null,"preventionTips":["Never JSON.stringify arrays or scalars into arguments; wrap them as { value: ... }.","Validate string arguments parse to a plain object at the adapter.","Prefer passing arguments as an object literal and let the projection serialize."],"tags":["codex","settled-turn","projection","tool-arguments","json","validation"],"backgroundTag":null,"analyzedSha":"01804a75319da4b69c9ab98ceaa30477e22b8c0b","analyzedAt":"2026-08-12T04:37:58.197Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}