{"record":{"id":"f404a92aad607114","repo":"zeroclaw-labs/zeroclaw","slug":"config-at-is-schema-version-from-run-zerocl","errorCode":null,"errorMessage":"config at {} is schema_version {from}; run `zeroclaw config migrate` to update before modifying","messagePattern":"config at (.+?) is schema_version (.+?); run `zeroclaw config migrate` to update before modifying","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/migration.rs","lineNumber":753,"sourceCode":"            return Err(anyhow::Error::from(e)).with_context(|| {\n                format!(\"failed to read config at {}\", path.display().to_string())\n            });\n        }\n    };\n    let value: toml::Value =\n        toml::from_str(&raw).context(\"failed to parse config TOML for version check\")?;\n    let from = detect_version(&value)?;\n    if from == CURRENT_SCHEMA_VERSION {\n        return Ok(());\n    }\n    if from > CURRENT_SCHEMA_VERSION {\n        anyhow::bail!(\n            \"config at {} is schema_version {from}, newer than this binary supports ({})\",\n            path.display().to_string(),\n            CURRENT_SCHEMA_VERSION,\n        );\n    }\n    anyhow::bail!(\n        \"config at {} is schema_version {from}; run `zeroclaw config migrate` to update before modifying\",\n        path.display().to_string(),\n    );\n}\n\npub(crate) fn fold_string_into_array(\n    table: &mut toml::Table,\n    from_key: &str,\n    to_key: &str,\n) -> bool {\n    let value = match table.remove(from_key) {\n        Some(toml::Value::String(s)) if !s.is_empty() => s,\n        Some(other) => {\n            // Non-string: re-insert under from_key untouched (caller may handle).\n            table.insert(from_key.to_string(), other);\n            return false;\n        }\n        None => return false,","sourceCodeStart":735,"sourceCodeEnd":771,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/migration.rs#L735-L771","documentation":"ensure_disk_at_current_version also refuses configs older than V3, but unlike the newer-than-binary case this one is recoverable in place: it directs you to run `zeroclaw config migrate`. Modifying APIs are gated on this check so stale-format files are never partially edited by code that assumes the current layout.","triggerScenarios":"A config whose detected schema_version is 1 or 2 is passed to any config-modifying entry point routed through ensure_disk_at_current_version. This is exactly what you hit after upgrading the binary across a schema boundary and trying to change settings before migrating.","commonSituations":"Upgrading ZeroClaw across a schema bump and editing settings before migrating; restoring an old config backup into a new install; sharing a config written by an older release.","solutions":["Run `zeroclaw config migrate` and let it walk the migration chain forward to V3.","Verify the file afterwards: schema_version = 3 at the top of the TOML, then retry the original operation.","Keep a backup before migrating (the chain is forward-only) in case a hand-edited field cannot be transformed.","If migration fails, inspect the file for hand-edited fields the steps cannot handle, fix or remove them, and re-run migrate."],"exampleFix":"// before\n$ zeroclaw config set runtime.kind docker\nError: config at ~/.config/zeroclaw/config.toml is schema_version 2; run `zeroclaw config migrate` to update before modifying\n\n// after\n$ zeroclaw config migrate\n$ zeroclaw config set runtime.kind docker   // succeeds","handlingStrategy":"try-catch","validationCode":"fn disk_version(raw: &str) -> Option<u32> {\n    toml::from_str::<toml::Value>(raw)\n        .ok()?\n        .get(\"schema_version\")?\n        .as_integer()\n        .map(|v| v as u32)\n}\n\nif let Some(v) = disk_version(&raw) {\n    if v < 3 { /* run `zeroclaw config migrate` (with a backup) before modifying */ }\n}","typeGuard":null,"tryCatchPattern":"match ensure_disk_at_current_version(&path) {\n    Err(e) if e.to_string().contains(\"zeroclaw config migrate\") => {\n        // back up the file, run the migrate command, then retry the original call once\n    }\n    other => other?,\n}","preventionTips":["Run `zeroclaw config migrate` immediately after upgrading across a schema bump.","Never hand-edit schema_version; let the migration chain own it.","Keep config migration as an explicit step in the upgrade runbook.","Keep a pre-migration backup since the chain is forward-only."],"tags":["config","migration","upgrade"],"backgroundTag":"config-schema-migration-required","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}