unicity-aos/aos-ce · error · io::Error
legacy runtime contains a non-UTF-8 top-level path
Error message
legacy runtime contains a non-UTF-8 top-level path
What it means
validate_source_layout iterates the top-level entries of the legacy runtime source directory and requires each name to be valid UTF-8; a non-UTF-8 top-level entry causes this InvalidInput error. The migration then classifies entries by known names (etc, bin, ...), so undecodable names are rejected upfront.
Solutions
- Rename or delete the non-UTF-8 top-level entry in the legacy runtime source
- Re-create the legacy source layout with standard UTF-8 names (etc, bin, etc.)
- Check entries with entry.file_name().to_str().is_some() before migrating
Example fix
// before legacy/ bin/ \xff\xfe-data/ # non-UTF-8 entry // after legacy/ bin/ data/
Defensive patterns
Strategy: validation
Validate before calling
fn legacy_top_level_utf8(source: &std::path::Path) -> bool {
std::fs::read_dir(source)
.map(|entries| entries.filter_map(|e| e.ok()).all(|e| e.file_name().to_str().is_some()))
.unwrap_or(false)
} Try / catch
match migrate_runtime(&source, ...) {
Ok(()) => {},
Err(e) if e.to_string().contains("non-UTF-8 top-level path") =>
eprintln!("clean the legacy runtime root: rename or delete undecodable entries"),
Err(e) => return Err(e),
} Prevention
- Audit legacy install roots for raw-byte filenames before migrating
- Re-create legacy layouts with standard names (etc, bin) when rebuilding from archives
- Mount source filesystems with UTF-8 name encoding enforced
- Run a pre-migration scan that flags entries where file_name().to_str() is None
When it happens
Trigger: Calling migrate_runtime when the legacy runtime source directory contains a top-level file or directory with a non-UTF-8 name.
Common situations: Legacy installs created by tooling that wrote raw-byte filenames; archive extractions with broken encodings; NFS/vfat mounts lacking UTF-8 name normalization.
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
- AOS capsule directory contains a non-UTF-8 entry
- AOS capsule directory must be valid UTF-8 for the TOML…
- imported principal home contains a non-UTF-8 name
- imported capsule installation contains a non-UTF-8 name
- product release runtime bin contains a non-UTF-8 entry
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/13aa9837dcbf0c06.
Report an issue: GitHub.
Appendix: source
Thrown at crates/unicity-aos-bootstrap/src/migration.rs:760
let entry = entry?;
let metadata = fs::symlink_metadata(entry.path())?;
if metadata.file_type().is_symlink() {
return invalid("packaged filesystem support contains a symlink");
}
if metadata.is_dir() {
validate_packaged_filesystem_directory(&entry.path())?;
} else if !metadata.is_file() {
return invalid("packaged filesystem support contains special data");
}
}
Ok(())
}
fn validate_source_layout(source: &Path) -> io::Result<()> {
for entry in fs::read_dir(source)? {
let entry = entry?;
let name = entry.file_name().into_string().map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidInput,
"legacy runtime contains a non-UTF-8 top-level path",
)
})?;
let known = name == "etc"
|| name == "bin"
|| PERSISTENT_TOP_LEVEL.contains(&name.as_str())
|| EPHEMERAL_TOP_LEVEL.contains(&name.as_str());
if !known {
return invalid(&format!(
"legacy runtime contains unsupported top-level state `{name}`; migration refuses to omit it"
));
}
}
Ok(())
}
fn copy_etc_state(source_root: &Path, staging: &Path, entries: &mut Vec<Entry>) -> io::Result<()> {View on GitHub (pinned to f6f22024fb)