astrid-runtime/astrid · error
legacy principal profile is not a regular file: {}
Error message
legacy principal profile is not a regular file: {} What it means
Thrown by ensure_profile_with_genesis_key when the legacy principal profile file is a symlink or not a regular file. During minting of a valid leftover into a new identity, the profile is read to extract the genesis key, and links or special files are rejected to prevent redirect-based attacks. Full symlink metadata is inspected rather than following the link.
Source
Thrown at crates/astrid-kernel/src/principal_home_migration/unbound.rs:157
{
identity
.bind_principal_identity(user.id, alias.clone(), public_key)
.await
.map_err(|error| identity_io(&error))?;
}
return Ok(user);
}
identity
.create_principal(alias.clone(), public_key)
.await
.map_err(|error| identity_io(&error))
}
fn ensure_profile_with_genesis_key(home: &AstridHome, alias: &PrincipalId) -> io::Result<()> {
let path = PrincipalProfile::path_for(home, alias);
let mut profile = match fs::symlink_metadata(&path) {
Ok(metadata) if metadata.file_type().is_symlink() || !metadata.is_file() => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"legacy principal profile is not a regular file: {}",
path.display()
),
));
},
Ok(_) => {
PrincipalProfile::load_required(home, alias).map_err(|error| profile_io(&error))?
},
Err(error) if error.kind() == io::ErrorKind::NotFound => PrincipalProfile::default(),
Err(error) => return Err(error),
};
let minted = mint_bootstrap_keypair(home, alias, &mut profile)?;
if minted || !path.is_file() {
profile
.save(home, alias)
.map_err(|error| profile_io(&error))?;View on GitHub (pinned to affd8760f4)
Solutions
- Replace the symlink/special file with a real regular profile file at the expected path.
- Remove the offending leftover entry so it is quarantined instead of minted, then re-run migration.
- Audit the legacy home for symlinks (find -type l) and flatten them before migrating.
- Restore the profile file from backup as a regular file, not a link.
Example fix
// before ln -s /shared/profiles/ali.json ~/.legacy/profiles/ali.json // after cp /shared/profiles/ali.json ~/.legacy/profiles/ali.json # regular file
Defensive patterns
Strategy: validation
Validate before calling
fn profile_is_regular_file(path: &Path) -> bool {
match fs::symlink_metadata(path) {
Ok(m) => !m.file_type().is_symlink() && m.is_file(),
Err(_) => false,
}
} Try / catch
match mint_valid_leftover(entry) {
Err(e) if e.to_string().contains("not a regular file") => {
// quarantine this leftover instead of minting
quarantine(entry)?;
}
other => other?,
} Prevention
- Audit legacy homes for symlinks (find -type l) and flatten before migration.
- Restore backups as regular files, never links.
- Do not point profile paths at directories, sockets, or FIFOs.
- Let the migration quarantine non-regular leftovers rather than force-minting them.
When it happens
Trigger: ensure_profile_with_genesis_key (called from mint_valid_leftover) calls fs::symlink_metadata on PrincipalProfile::path_for(home, alias) and finds the path is a symlink or not a regular file (directory, socket, FIFO, device).
Common situations: A leftover entry in the legacy home is actually a directory (e.g. a nested home) rather than a profile file; symlinks were used to organize legacy homes; a file was replaced by a socket/FIFO by another tool; partially restored backups left links behind.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- legacy principal home root is not a regular directory: {}
- layout migration destination is redirected or not a regular
- layout migration source is redirected or not a directory: {}
- legacy state source is redirected: {}
- legacy state source contains a redirect: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/b3915d5d0caa55a0.
Report an issue: GitHub.