zeroclaw-labs/zeroclaw · error · anyhow::Error
AIEOS payload must be a JSON object
Error message
AIEOS payload must be a JSON object
What it means
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.
Source
Thrown at crates/zeroclaw-runtime/src/identity.rs:215
"Identity format is set to 'aieos' but neither aieos_path nor aieos_inline is configured. \
Set one in your config:\n\
\n\
[identity]\n\
format = \"aieos\"\n\
aieos_path = \"identity.json\"\n\
\n\
Or use inline:\n\
\n\
[identity]\n\
format = \"aieos\"\n\
aieos_inline = '{{\"identity\": {{...}}}}'"
)
}
fn parse_aieos_identity(content: &str) -> Result<AieosIdentity> {
let payload: Value = serde_json::from_str(content).context("Invalid AIEOS JSON")?;
if !payload.is_object() {
anyhow::bail!("AIEOS payload must be a JSON object")
}
Ok(normalize_aieos_identity(&payload))
}
fn normalize_aieos_identity(payload: &Value) -> AieosIdentity {
AieosIdentity {
identity: normalize_identity_section(value_at_path(payload, &["identity"])),
psychology: normalize_psychology_section(value_at_path(payload, &["psychology"])),
linguistics: normalize_linguistics_section(value_at_path(payload, &["linguistics"])),
motivations: normalize_motivations_section(value_at_path(payload, &["motivations"])),
capabilities: normalize_capabilities_section(value_at_path(payload, &["capabilities"])),
physicality: normalize_physicality_section(value_at_path(payload, &["physicality"])),
history: normalize_history_section(value_at_path(payload, &["history"])),
interests: normalize_interests_section(value_at_path(payload, &["interests"])),
}
}
fn normalize_identity_section(section: Option<&Value>) -> Option<IdentitySection> {View on GitHub (pinned to 88bb9c8533)
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
Example fix
// before (identity.json)
[{ "identity": { "name": "Claw" } }]
// after
{ "identity": { "name": "Claw" } } Defensive patterns
Strategy: validation
Validate before calling
let parsed: serde_json::Value = serde_json::from_str(&content)
.context("Invalid AIEOS JSON")?;
if !parsed.is_object() {
anyhow::bail!("AIEOS payload must be a JSON object");
} Type guard
fn is_aieos_payload(v: &serde_json::Value) -> bool {
v.is_object()
} Try / catch
match parse_aieos_identity(&content) {
Ok(id) => id,
Err(e) if e.to_string().contains("must be a JSON object") => {
// shape problem: fix the document (root must be an object), do not retry as-is
}
Err(e) => return Err(e), // e.g. "Invalid AIEOS JSON" context — syntax problem
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- cloud_ops.iac_tools must not be empty when cloud_ops is enab
- gateway.path_prefix contains invalid character '{bad}'; only
- risk_profiles.{profile_alias}.shell_env_passthrough[{i}] is
- security.otp.cache_valid_secs must be greater than or equal
- security.otp.gated_actions[{i}] contains invalid characters:
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/af898f7adf96b892.
Report an issue: GitHub.