astrid-runtime/astrid · error

legacy principal-home source {path}: principal directory nam

Error message

legacy principal-home source {path}: principal directory name is not UTF-8

What it means

Raised when a directory entry in the legacy principal-home source root has a filename that is not valid UTF-8. Principal identifiers are text, so a non-UTF-8 directory name cannot be interpreted as a principal alias. Reported via invalid_source with ErrorKind::InvalidData.

Source

Thrown at crates/astrid-kernel/src/principal_home_migration/mod.rs:96

    }
    astrid_core::platform_fs::ensure_private_directory_tree(&source_root)?;
    astrid_core::platform_fs::verify_no_redirects(&source_root)?;
    astrid_core::platform_fs::ensure_private_directory(&home.migrations_dir())?;

    let entries = fs::read_dir(&source_root).map_err(|error| {
        io::Error::new(
            error.kind(),
            format!("scan {}: {error}", source_root.display()),
        )
    })?;
    for entry in entries {
        let entry = entry?;
        let alias_name = entry.file_name();
        let alias_text = alias_name.to_str().ok_or_else(|| {
            invalid_source(&entry.path(), "principal directory name is not UTF-8")
        })?;
        let alias = PrincipalId::new(alias_text.to_owned()).map_err(|error| {
            io::Error::new(
                io::ErrorKind::InvalidData,
                format!("legacy principal directory {alias_text:?} is invalid: {error}"),
            )
        })?;
        // 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,

View on GitHub (pinned to affd8760f4)

Solutions

  1. Rename the offending directory to a valid UTF-8 principal name
  2. Remove the non-UTF-8 entry if it is junk
  3. Find it with: find <source_root> -maxdepth 1 | grep -vP '[\x00-\x7F]*'
  4. Re-run migration after cleaning the directory listing

Example fix

// before: rename non-UTF-8 entry manually
mv $'home/bad\xffname' home/badname
// after: migration proceeds
migrate_legacy_principal_homes(&home, &store)?;
Defensive patterns

Strategy: validation

Validate before calling

fn alias_names_ok(root: &Path) -> bool {
    std::fs::read_dir(root).map(|rd| rd.filter_map(Result::ok).all(|e| e.file_name().to_str().is_some())).unwrap_or(false)
}

Type guard

fn is_utf8_entry(e: &std::fs::DirEntry) -> bool { e.file_name().to_str().is_some() }

Try / catch

match result {
    Err(e) if e.kind() == io::ErrorKind::InvalidData && e.to_string().contains("not UTF-8") => {
        rename_non_utf8_entries(&source_root)?;
        retry()
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling migrate_legacy_principal_homes when an entry under the source root has a non-UTF-8 name, typically from files created with raw bytes (e.g. on Linux filesystems that allow arbitrary byte names).

Common situations: Directories created by non-Rust tools with locale-mismatched encoding, accidentally extracted archives with binary-named entries, NFS mounts with different encodings.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/273d110772fd7306. Report an issue: GitHub.