astrid-runtime/astrid · error
legacy capsule entry has a non-UTF-8 name
Error message
legacy capsule entry has a non-UTF-8 name
What it means
During native-to-legacy capsule migration, `migrate_native_capsules_with_report` uses each installed capsule directory's `file_name()` as the capsule id. If that directory name is not valid UTF-8, `to_str()` fails and this error aborts migration for that entry. The id must be a UTF-8 string because it is later compared against the manifest's `package.name` and used in receipts/receipt paths.
Source
Thrown at crates/astrid-capsule-install/src/storage/migration.rs:130
);
}
astrid_core::platform_fs::verify_no_redirects(&native)
.with_context(|| format!("verify legacy capsule root {}", native.display()))?;
let mut children = read_dir_sorted(&native)?;
let mut report = LegacyCapsuleMigrationReport::default();
let registry = store.capsules();
let owner = StateOwner::Principal(uid);
for (target, target_metadata) in children.drain(..) {
if target_metadata.file_type().is_symlink() || !target_metadata.is_dir() {
bail!(
"legacy capsule entry is not a regular directory: {}",
target.display()
);
}
let id = target
.file_name()
.and_then(|name| name.to_str())
.ok_or_else(|| anyhow::anyhow!("legacy capsule entry has a non-UTF-8 name"))?;
let manifest = astrid_capsule::discovery::load_manifest(&target.join("Capsule.toml"))
.with_context(|| format!("read legacy capsule manifest {id}"))?;
if manifest.package.name != id {
bail!(
"legacy capsule directory {id} does not match manifest id {}",
manifest.package.name
);
}
let meta_bytes = fs::read(target.join("meta.json"))
.with_context(|| format!("read legacy capsule metadata {id}"))?;
let meta: CapsuleMeta = serde_json::from_slice(&meta_bytes)
.with_context(|| format!("decode legacy capsule metadata {id}"))?;
if meta.version != manifest.package.version {
bail!("legacy capsule metadata version differs for {id}");
}
// Released pre-authority installs are admitted only through the
// existing one-time verifier. It pins their exact manifest,
// capabilities, and executable before any durable publication.View on GitHub (pinned to affd8760f4)
Solutions
- Rename the offending capsule directory under the native capsule home to its correct UTF-8 id (must match the `Capsule.toml` `package.name`)
- Delete the corrupt directory and reinstall the capsule so the id is derived from a clean manifest
- Enumerate candidates first with `find <capsules-home> -maxdepth 1 | grep -Pv '^[\x20-\x7E]+$'` to identify non-ASCII names before migrating
Example fix
// before capsules/ caf\xe9-tools/ # non-UTF-8 dir name // after $ mv capsules/$(printf 'caf\xe9-tools') capsules/cafe-tools $ migrate_native_capsules(home)?;
Defensive patterns
Strategy: validation
Validate before calling
fn assert_capsule_ids_utf8(capsules_dir: &Path) -> anyhow::Result<()> {
for entry in std::fs::read_dir(capsules_dir)? {
let entry = entry?;
anyhow::ensure!(entry.file_name().to_str().is_some(),
"non-UTF-8 capsule dir: {:?}", entry.file_name());
}
Ok(())
}
assert_capsule_ids_utf8(&home.join("capsules"))?; Type guard
fn is_utf8_dir_name(entry: &std::fs::DirEntry) -> bool {
entry.file_name().to_str().is_some()
} Try / catch
match migrate_native_capsules(home) {
Err(e) if e.to_string().contains("non-UTF-8 name") => {
// rename the offending directory to its manifest id, then retry
}
Err(e) => return Err(e),
Ok(r) => r,
} Prevention
- Only create capsule directories from manifest ids (UTF-8 by construction)
- Pre-flight the capsules directory for non-ASCII names before running migration
- Run migration under a UTF-8 locale
- Skip-and-report instead of hard-fail when a single legacy entry has an unusable name, if the API surface allows a report-based migration
When it happens
Trigger: Running `migrate_native_capsules`/`migrate_all_native_capsules_with_report` when the native capsule store contains a directory whose name has non-UTF-8 bytes; the function reads the target directory listing and one `file_name()` fails `to_str()`.
Common situations: Capsule directories created by scripts in a non-UTF-8 locale; corrupted or manually copied directory names; upgrading machines where the capsules directory was populated with legacy 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
- capsule path is not valid UTF-8
- layout cutover record is not a regular file: {}
- layout cutover record is empty: {}
- legacy source changed before retirement: {}
- legacy retirement root is not a directory: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/1f0c038fd7813918.
Report an issue: GitHub.