astrid-runtime/astrid · critical · io::Error
Unsupported
Unsupported
Error message
legacy principal {alias} (uid {uid}) retains unsupported {name} state; no authoritative migration API exists: {} What it means
Thrown by ensure_no_unretired_component_sources when a legacy principal retains non-empty kv/ or tokens/ state in its old home. These components have no authoritative migration API, so the kernel cannot convert the data; it fails with io::ErrorKind::Unsupported instead of silently dropping it.
Source
Thrown at crates/astrid-kernel/src/legacy_migration_barrier/mod.rs:832
),
));
}
}
for (alias, uid) in directory.bindings() {
let root = home.principal_home(&alias).root().to_path_buf();
if !path_exists(&root)? {
continue;
}
let unsupported = [
("kv", home.principal_home(&alias).kv_dir()),
("tokens", home.principal_home(&alias).tokens_dir()),
];
for (name, path) in unsupported {
if !path_exists(&path)? {
continue;
}
if snapshot_path(&path)?.entries != 0 {
return Err(io::Error::new(
io::ErrorKind::Unsupported,
format!(
"legacy principal {alias} (uid {uid}) retains unsupported {name} state; no authoritative migration API exists: {}",
path.display()
),
));
}
if allow_empty_cleanup {
retire_empty_directory(&path)?;
} else {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"legacy {name} source reappeared after cut-over: {}",
path.display()
),
));
}View on GitHub (pinned to affd8760f4)
Solutions
- Manually export/archive the kv/ and tokens/ contents, then empty the directories before re-running cut-over.
- Confirm no component still writes to these directories (stop legacy agents) and clear the data.
- If the state is obsolete, delete the non-empty legacy kv/tokens directories after backing them up.
- Escalate/feature-request an authoritative migration path if the data must be preserved in v2.
Example fix
// before cut_over(...)?; // Unsupported: kv/ has 37 entries, no migration API // after archive_dir(principal_home.kv_dir(), "/backup/alice-kv")?; archive_dir(principal_home.tokens_dir(), "/backup/alice-tokens")?; // directories now empty -> cut-over proceeds
Defensive patterns
Strategy: validation
Validate before calling
for dir in [home.principal_home(&alias).kv_dir(), home.principal_home(&alias).tokens_dir()] {
if path_exists(&dir)? && snapshot_path(&dir)?.entries != 0 {
// archive/export manually — no automatic migration exists
}
} Type guard
fn unsupported_state_empty(home: &AstridHome, alias: &PrincipalId) -> io::Result<bool> {
let p = home.principal_home(alias);
Ok(!path_exists(p.kv_dir())? && !path_exists(p.tokens_dir())?)
} Try / catch
match cut_over(&home, &dir) {
Err(e) if e.kind() == io::ErrorKind::Unsupported => {
archive_and_clear_unsupported_state(&home)?;
retry_cut_over()?;
}
other => other?,
} Prevention
- Inventory legacy kv/ and tokens/ usage across all principals before planning migration.
- Archive these directories during decommissioning since no importer exists.
- Monitor for new writes to these dirs; treat non-empty kv/tokens as a migration blocker.
When it happens
Trigger: Cut-over verification finds <principal-home>/kv/ or <principal-home>/tokens/ present with snapshot.entries != 0 for any bound principal alias.
Common situations: Principal actively used legacy KV or token storage that the current migration pipeline never supported; long-idle principal whose legacy state was never cleaned; operator assumed empty-dir cleanup would suffice but data remained.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- unsupported legacy audit source {audit_source}; only the def
- legacy capsule entry has a non-UTF-8 name
- legacy capsule {id} authority verification produced no recei
- legacy capsule {id} authority receipt disappeared
- durable capsule {id} disappeared after publish
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/42305138f0ad0bca.
Report an issue: GitHub.