zeroclaw-labs/zeroclaw · error · anyhow::Error
target V{target} exceeds CURRENT_SCHEMA_VERSION (V{CURRENT_S
Error message
target V{target} exceeds CURRENT_SCHEMA_VERSION (V{CURRENT_SCHEMA_VERSION}) What it means
run_chain_until refuses any target above CURRENT_SCHEMA_VERSION because migration steps only exist up to the compiled version (V3). This is the bounds check that keeps the MIGRATION_STEPS[from..target] slice from indexing past its end, and it catches requests for schema versions the running binary cannot produce.
Source
Thrown at crates/zeroclaw-config/src/migration.rs:829
const _: () = assert!(
MIGRATION_STEPS.len() as u32 == CURRENT_SCHEMA_VERSION,
"MIGRATION_STEPS must have exactly one entry per schema version \
(length = CURRENT_SCHEMA_VERSION, including the slot-0 padding)",
);
/// Run the typed migration chain from `from` up to `CURRENT_SCHEMA_VERSION`.
/// `from` must be `< CURRENT_SCHEMA_VERSION` (caller checks).
fn run_chain(value: toml::Value, from: u32) -> Result<toml::Value> {
run_chain_until(value, from, CURRENT_SCHEMA_VERSION)
}
fn run_chain_until(value: toml::Value, from: u32, target: u32) -> Result<toml::Value> {
if target < from {
anyhow::bail!("cannot migrate backwards from V{from} to V{target}");
}
if target > CURRENT_SCHEMA_VERSION {
anyhow::bail!(
"target V{target} exceeds CURRENT_SCHEMA_VERSION (V{CURRENT_SCHEMA_VERSION})"
);
}
let mut cur = value;
for step in &MIGRATION_STEPS[from as usize..target as usize] {
cur = step(cur)?;
}
Ok(cur)
}
pub(crate) fn sync_table(doc: &mut toml_edit::Table, new: &toml::Table) {
// Drop keys not present in new
let to_remove: Vec<String> = doc
.iter()
.map(|(k, _)| k.to_string())
.filter(|k| !new.contains_key(k))
.collect();View on GitHub (pinned to 88bb9c8533)
Solutions
- Use CURRENT_SCHEMA_VERSION as the target instead of a literal number.
- Upgrade the binary if you genuinely need the newer schema version.
- Validate or clamp the target argument before calling the chain.
Example fix
// before let migrated = run_chain_until(value, from, 4)?; // target exceeds CURRENT_SCHEMA_VERSION // after let migrated = run_chain_until(value, from, CURRENT_SCHEMA_VERSION)?;
Defensive patterns
Strategy: validation
Validate before calling
// never hardcode a schema literal; derive it let target = target.min(CURRENT_SCHEMA_VERSION); assert!(target >= from, "downgrades unsupported"); let migrated = run_chain_until(value, from, target)?;
Try / catch
match run_chain_until(value, from, target) {
Err(e) if e.to_string().contains("exceeds CURRENT_SCHEMA_VERSION") => {
// retry with target = CURRENT_SCHEMA_VERSION
}
other => other?,
} Prevention
- Always pass CURRENT_SCHEMA_VERSION rather than a number literal.
- Validate externally sourced version values against the binary's supported range.
- Remember the supported ceiling changes with the binary version; re-check after upgrades.
When it happens
Trigger: Calling run_chain_until(value, from, target) with target > 3 — e.g. requesting generate() at V4 on a V3 binary, or forwarding a hardcoded future version that outlived the binary it was written against.
Common situations: Code written against a newer ZeroClaw that hardcodes a higher target version; a user-supplied version from config or CLI forwarded unclamped into the migration chain.
Related errors
- config at {} is schema_version {from}, newer than this binar
- config at {} is schema_version {from}; run `zeroclaw config
- memory backend 'none' disables persistence; choose sqlite, l
- unsupported room visibility '{other}': expected private or p
- channel '{}' does not support forge API requests
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/2c453935872d972f.
Report an issue: GitHub.