{"record":{"id":"13aa9837dcbf0c06","repo":"unicity-aos/aos-ce","slug":"legacy-runtime-contains-a-non-utf-8-top-level-path","errorCode":null,"errorMessage":"legacy runtime contains a non-UTF-8 top-level path","messagePattern":"legacy runtime contains a non-UTF-8 top-level path","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/unicity-aos-bootstrap/src/migration.rs","lineNumber":760,"sourceCode":"        let entry = entry?;\n        let metadata = fs::symlink_metadata(entry.path())?;\n        if metadata.file_type().is_symlink() {\n            return invalid(\"packaged filesystem support contains a symlink\");\n        }\n        if metadata.is_dir() {\n            validate_packaged_filesystem_directory(&entry.path())?;\n        } else if !metadata.is_file() {\n            return invalid(\"packaged filesystem support contains special data\");\n        }\n    }\n    Ok(())\n}\n\nfn validate_source_layout(source: &Path) -> io::Result<()> {\n    for entry in fs::read_dir(source)? {\n        let entry = entry?;\n        let name = entry.file_name().into_string().map_err(|_| {\n            io::Error::new(\n                io::ErrorKind::InvalidInput,\n                \"legacy runtime contains a non-UTF-8 top-level path\",\n            )\n        })?;\n        let known = name == \"etc\"\n            || name == \"bin\"\n            || PERSISTENT_TOP_LEVEL.contains(&name.as_str())\n            || EPHEMERAL_TOP_LEVEL.contains(&name.as_str());\n        if !known {\n            return invalid(&format!(\n                \"legacy runtime contains unsupported top-level state `{name}`; migration refuses to omit it\"\n            ));\n        }\n    }\n    Ok(())\n}\n\nfn copy_etc_state(source_root: &Path, staging: &Path, entries: &mut Vec<Entry>) -> io::Result<()> {","sourceCodeStart":742,"sourceCodeEnd":778,"githubUrl":"https://github.com/unicity-aos/aos-ce/blob/f6f22024fb1e8d122f28a1b4a9f75aee448ae839/crates/unicity-aos-bootstrap/src/migration.rs#L742-L778","documentation":"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.","triggerScenarios":"Calling migrate_runtime when the legacy runtime source directory contains a top-level file or directory with a non-UTF-8 name.","commonSituations":"Legacy installs created by tooling that wrote raw-byte filenames; archive extractions with broken encodings; NFS/vfat mounts lacking UTF-8 name normalization.","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"],"exampleFix":"// before\nlegacy/\n  bin/\n  \\xff\\xfe-data/   # non-UTF-8 entry\n\n// after\nlegacy/\n  bin/\n  data/","handlingStrategy":"validation","validationCode":"fn legacy_top_level_utf8(source: &std::path::Path) -> bool {\n    std::fs::read_dir(source)\n        .map(|entries| entries.filter_map(|e| e.ok()).all(|e| e.file_name().to_str().is_some()))\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match migrate_runtime(&source, ...) {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"non-UTF-8 top-level path\") =>\n        eprintln!(\"clean the legacy runtime root: rename or delete undecodable entries\"),\n    Err(e) => return Err(e),\n}","preventionTips":["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"],"tags":["rust","filesystem","encoding"],"backgroundTag":"invalid-identifier-format","analyzedSha":"f6f22024fb1e8d122f28a1b4a9f75aee448ae839","analyzedAt":"2026-09-13T03:04:44.565Z","contentChangedAt":"2026-09-13T03:04:44.565Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}