astrid-runtime/astrid · error
legacy principal has no durable UID
Error message
legacy principal {alias} has no durable UID What it means
Raised when neither a migration receipt nor a live alias binding provides a durable UID for a legacy principal. Migration needs a stable UID to associate the principal's data; without one it cannot proceed and returns InvalidData.
Solutions
- Restore the missing receipt or live alias binding (re-register the principal)
- Reconstruct the durable UID from backups of the alias store
- Remove the orphaned legacy principal directory if the principal no longer exists
- Re-run migration once a durable UID is available
Example fix
// before: orphaned legacy dir aborts migration migrate_legacy_principal_homes(&home, &store)?; // after: re-register or remove the orphan first ensure_principal_registered(&store, &alias)?; migrate_legacy_principal_homes(&home, &store)?;
Defensive patterns
Strategy: validation
Validate before calling
fn principal_resolvable(store: &Store, alias: &str) -> bool {
store.receipt_for(alias).is_some() || store.live_binding(alias).is_some()
} Type guard
fn has_durable_uid(r: Option<&Receipt>, l: Option<&Binding>) -> bool { r.is_some() || l.is_some() } Try / catch
match migrate_legacy_principal_homes(&home, &store) {
Err(e) if e.kind() == io::ErrorKind::InvalidData => {
re_register_orphaned_principals(&store)?;
migrate_legacy_principal_homes(&home, &store)
}
other => other,
} Prevention
- Never delete migration receipts independently of the alias store
- Back up the alias store before touching legacy directories
- Re-register principals whose live bindings were removed before migrating
When it happens
Trigger: Calling migrate_legacy_principal_homes when for a given alias both the migration receipt and the live alias binding are absent (the (None, None) match arm), e.g. the receipt file was deleted and the alias store has no record.
Common situations: Partially cleaned state after manual deletion of receipts, a store that was reset while legacy directories remain, or migration re-run against a pruned store.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- principal has an invalid genesis public key
- principal has no Ed25519 key for genesis identity
- absent migration source has a digest
- automatic migration of unreleased Windows layout-one homes…
- cannot migrate an Astrid home without a layout-version…
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/3b6544f7e94d9ffc.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-kernel/src/principal_home_migration/mod.rs:117
)
})?;
// A migration receipt is immutable provenance and takes precedence
// over the mutable alias directory. If an alias was deleted and then
// reused, never stream the surviving old source into the replacement
// UID; fail closed instead.
let receipt_uid = receipt_uid_for_alias(home, &alias)?;
let live_uid = principals.uid_for(&alias).ok();
let uid = match (receipt_uid, live_uid) {
(Some(receipt), Some(live)) if receipt != live => {
return Err(conflict_path(
&entry.path(),
"migration receipt UID differs from the live alias binding",
));
},
(Some(receipt), _) => receipt,
(None, Some(live)) => live,
(None, None) => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("legacy principal {alias} has no durable UID"),
));
},
};
migrate_one_principal(home, store, uid, &alias, &entry.path())?;
}
Ok(())
}
/// Snapshot only ordinary entries owned by this migration.
///
/// Dedicated subtrees (capsules, env, audit, logs, and other released
/// operational paths) are excluded because their own migrations bind and
/// retire them. The fields use the same digest/count/byte inventory as the
/// ordinary-home receipt. `present` distinguishes an absent source from an
/// existing source containing only dedicated entries.
#[derive(Clone, Debug, PartialEq, Eq)]View on GitHub (pinned to affd8760f4)