{"record":{"id":"af898f7adf96b892","repo":"zeroclaw-labs/zeroclaw","slug":"aieos-payload-must-be-a-json-object","errorCode":null,"errorMessage":"AIEOS payload must be a JSON object","messagePattern":"AIEOS payload must be a JSON object","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/identity.rs","lineNumber":215,"sourceCode":"        \"Identity format is set to 'aieos' but neither aieos_path nor aieos_inline is configured. \\\n         Set one in your config:\\n\\\n         \\n\\\n         [identity]\\n\\\n         format = \\\"aieos\\\"\\n\\\n         aieos_path = \\\"identity.json\\\"\\n\\\n         \\n\\\n         Or use inline:\\n\\\n         \\n\\\n         [identity]\\n\\\n         format = \\\"aieos\\\"\\n\\\n         aieos_inline = '{{\\\"identity\\\": {{...}}}}'\"\n    )\n}\n\nfn parse_aieos_identity(content: &str) -> Result<AieosIdentity> {\n    let payload: Value = serde_json::from_str(content).context(\"Invalid AIEOS JSON\")?;\n    if !payload.is_object() {\n        anyhow::bail!(\"AIEOS payload must be a JSON object\")\n    }\n    Ok(normalize_aieos_identity(&payload))\n}\n\nfn normalize_aieos_identity(payload: &Value) -> AieosIdentity {\n    AieosIdentity {\n        identity: normalize_identity_section(value_at_path(payload, &[\"identity\"])),\n        psychology: normalize_psychology_section(value_at_path(payload, &[\"psychology\"])),\n        linguistics: normalize_linguistics_section(value_at_path(payload, &[\"linguistics\"])),\n        motivations: normalize_motivations_section(value_at_path(payload, &[\"motivations\"])),\n        capabilities: normalize_capabilities_section(value_at_path(payload, &[\"capabilities\"])),\n        physicality: normalize_physicality_section(value_at_path(payload, &[\"physicality\"])),\n        history: normalize_history_section(value_at_path(payload, &[\"history\"])),\n        interests: normalize_interests_section(value_at_path(payload, &[\"interests\"])),\n    }\n}\n\nfn normalize_identity_section(section: Option<&Value>) -> Option<IdentitySection> {","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/identity.rs#L197-L233","documentation":"parse_aieos_identity runs serde_json::from_str on the AIEOS document and then requires the top-level value to be a JSON object. Valid JSON whose root is an array, string, number, or boolean is rejected because normalize_aieos_identity reads named sections (identity, psychology, linguistics, ...) off an object map. The preceding context \"Invalid AIEOS JSON\" covers syntactic failures; this bail covers shape failures.","triggerScenarios":"aieos_path points at a file like [{\"identity\": ...}] (root array) or \"just a string\"; aieos_inline is double-encoded — a JSON string containing JSON (\"{\"identity\": ...}\"), so the root parses as a string; a generator exported a bare array of personas instead of a single object.","commonSituations":"Hand-editing identity.json and wrapping it in brackets; passing a JSONL/array export where one object is expected; serializing with an extra json!()/to_string() layer before storing into aieos_inline; jq output of `.[0]` style queries leaving array roots.","solutions":["Make the document root an object: {\"identity\": {...}, \"psychology\": {...}, ...}","If the payload is double-encoded, decode one layer so the root is an object, not a quoted string","Validate before running: jq -e 'type == \"object\"' identity.json exits non-zero for wrong shapes","If exporting from a generator, pick the single-persona object output mode, not the list export"],"exampleFix":"// before (identity.json)\n[{ \"identity\": { \"name\": \"Claw\" } }]\n\n// after\n{ \"identity\": { \"name\": \"Claw\" } }","handlingStrategy":"validation","validationCode":"let parsed: serde_json::Value = serde_json::from_str(&content)\n    .context(\"Invalid AIEOS JSON\")?;\nif !parsed.is_object() {\n    anyhow::bail!(\"AIEOS payload must be a JSON object\");\n}","typeGuard":"fn is_aieos_payload(v: &serde_json::Value) -> bool {\n    v.is_object()\n}","tryCatchPattern":"match parse_aieos_identity(&content) {\n    Ok(id) => id,\n    Err(e) if e.to_string().contains(\"must be a JSON object\") => {\n        // shape problem: fix the document (root must be an object), do not retry as-is\n    }\n    Err(e) => return Err(e), // e.g. \"Invalid AIEOS JSON\" context — syntax problem\n}","preventionTips":["Validate identity documents in CI with jq -e 'type == \"object\"'","When serializing aieos_inline, serialize once — never to_string a value that is already a string","Pin the AIEOS generator output format and add a schema smoke test for it"],"tags":["rust","zeroclaw","json","identity","validation","serde"],"backgroundTag":"json-shape-validation","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}