{"record":{"id":"a05129253391fde7","repo":"unicity-aos/aos-ce","slug":"legacy-runtime-etc-contains-a-non-utf-8-path","errorCode":null,"errorMessage":"legacy runtime etc contains a non-UTF-8 path","messagePattern":"legacy runtime etc contains a non-UTF-8 path","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/unicity-aos-bootstrap/src/migration.rs","lineNumber":792,"sourceCode":"    }\n    Ok(())\n}\n\nfn copy_etc_state(source_root: &Path, staging: &Path, entries: &mut Vec<Entry>) -> io::Result<()> {\n    let source = source_root.join(\"etc\");\n    let metadata = match fs::symlink_metadata(&source) {\n        Ok(metadata) => metadata,\n        Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(()),\n        Err(error) => return Err(error),\n    };\n    if metadata.file_type().is_symlink() || !metadata.is_dir() {\n        return invalid(\"legacy runtime etc must be a real directory\");\n    }\n\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 etc contains a non-UTF-8 path\",\n            )\n        })?;\n        if !ETC_ALLOWLIST.contains(&name.as_str()) {\n            return invalid(&format!(\n                \"legacy runtime contains unsupported configuration `etc/{name}`; migration refuses to omit it\"\n            ));\n        }\n        let relative = PathBuf::from(\"etc\").join(&name);\n        copy_tree(&entry.path(), &staging.join(&relative), &relative, entries)?;\n    }\n    Ok(())\n}\n\nfn copy_if_present(\n    source: &Path,\n    destination: &Path,","sourceCodeStart":774,"sourceCodeEnd":810,"githubUrl":"https://github.com/unicity-aos/aos-ce/blob/f6f22024fb1e8d122f28a1b4a9f75aee448ae839/crates/unicity-aos-bootstrap/src/migration.rs#L774-L810","documentation":"copy_etc_state reads the legacy runtime's etc directory and converts each entry name to String so it can be checked against ETC_ALLOWLIST; a non-UTF-8 name inside etc produces this InvalidInput error. It prevents copying unknown, undecodable config paths into the new runtime layout.","triggerScenarios":"Calling migrate_runtime when a file or subdirectory inside the legacy runtime's etc/ has a non-UTF-8 name, or a name not on ETC_ALLOWLIST (which then yields the adjacent invalid-name error).","commonSituations":"Old config dirs containing files created with legacy encodings; manually dropped-in config files with binary names; extraneous config files added after the original install.","solutions":["Rename or remove the non-UTF-8 entry inside legacy etc/ so only allowlisted names remain","Move unknown config files out of etc/ (back them up) before migrating","List etc/ contents and verify each name decodes as UTF-8 and appears in the allowlist before running migration"],"exampleFix":"// before\nlegacy/etc/\n  config.toml\n  \\x80backup/\n\n// after\nlegacy/etc/\n  config.toml","handlingStrategy":"validation","validationCode":"fn etc_entries_clean(etc: &std::path::Path, allowlist: &[&str]) -> bool {\n    std::fs::read_dir(etc)\n        .map(|entries| entries.filter_map(|e| e.ok()).all(|e| {\n            e.file_name().to_str().map(|n| allowlist.contains(&n)).unwrap_or(false)\n        }))\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match migrate_runtime(&source, ...) {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"etc contains a non-UTF-8 path\") =>\n        eprintln!(\"remove or rename undecodable entries under legacy etc/ before migrating\"),\n    Err(e) => return Err(e),\n}","preventionTips":["Keep only allowlisted config files in legacy etc/; move extras elsewhere first","Back up and remove files with undecodable names before migration","Validate etc/ contents (UTF-8 + allowlist membership) as a pre-flight step","Restrict write access to etc/ so foreign tools cannot drop arbitrary files there"],"tags":["rust","filesystem","encoding","migration"],"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"}