{"record":{"id":"1456652abcaeb7fc","repo":"AprilNEA/OpenLogi","slug":"resumable-fixture-cases-contain-a-non-utf-8-entry","errorCode":null,"errorMessage":"resumable fixture cases contain a non-UTF-8 entry","messagePattern":"resumable fixture cases contain a non-UTF-8 entry","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/contribute.rs","lineNumber":310,"sourceCode":"                \"in-progress contribution contains unexpected entry {other:?}; refusing to \\\n                 publish over it\"\n            ),\n            None => bail!(\"in-progress contribution contains a non-UTF-8 entry\"),\n        }\n    }\n    Ok(())\n}\n\nfn validate_resumable_cases(directory: &Path, cassettes: &[HidCassette]) -> Result<()> {\n    let expected = cassettes\n        .iter()\n        .map(|cassette| format!(\"{}.json\", cassette.name))\n        .collect::<Vec<_>>();\n    for entry in fs::read_dir(directory).context(\"could not inspect resumable fixture cases\")? {\n        let entry = entry.context(\"could not inspect resumable fixture case\")?;\n        let name = entry.file_name();\n        let Some(name) = name.to_str() else {\n            bail!(\"resumable fixture cases contain a non-UTF-8 entry\");\n        };\n        if !expected.iter().any(|expected| expected == name) {\n            bail!(\"resumable fixture cases contain unexpected file {name:?}\");\n        }\n        require_regular_file(&entry.path(), \"fixture cassette\")?;\n    }\n    Ok(())\n}\n\nfn identity_plan(\n    profile: &DeviceProfile,\n    selected_route: &DeviceRoute,\n) -> Result<HidCassetteIdentityPlan> {\n    let mut plan = HidCassetteIdentityPlan::default();\n    let model = match selected_route {\n        DeviceRoute::Bolt { receiver_uid, slot } => {\n            plan.insert(\n                SanitizedIdentityKind::ReceiverUniqueId,","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/contribute.rs#L292-L328","documentation":"During a resumed `openlogi fixture contribute` run, validate_resumable_cases scans the saved `cases/` directory of the in-progress contribution and requires every directory entry name to be valid UTF-8 before comparing it against the expected cassette filenames. If any entry's file name cannot be converted to a Rust `str` (OsStr not valid UTF-8), the CLI refuses to proceed. This guards the publish path from writing over a corrupted or hand-mangled resumable state directory.","triggerScenarios":"Resuming a contribution (`openlogi fixture contribute` with an existing state file) while the `<output>/cases/` directory contains any file or subdirectory whose name is not valid UTF-8 — e.g. a file created with raw bytes from a Linux tool, a name with invalid-encoded characters, or a corrupted entry produced by a filesystem crash.","commonSituations":"Developers on Linux who dropped temporary files with arbitrary byte names into the cases directory; rsync/backup restores that mangled non-ASCII cassette names; manually editing or cleaning the in-progress fixture output directory mid-contribution; a disk-level corruption leaving a garbage-named entry.","solutions":["List the cases directory (`ls -b <output>/cases/`) and find the entry whose name prints with escape sequences","Delete or rename the non-UTF-8 entry to a name matching an expected cassette `<name>.json`, or remove it if it is stray","If the directory is badly mangled, delete the resumable state file and restart the contribution from scratch","Only create/edit files in the fixture output directory using UTF-8-safe tools"],"exampleFix":"// before (shell): stray file with raw-byte name in the resumable output\n$ ls output/cases/\nmy-cassette.json  '\\xff\\xfe.tmp'\n// after: remove or rename the invalid entry, then rerun\n$ rm output/cases/'\\xff\\xfe.tmp'\n$ openlogi fixture contribute ...  # resumes cleanly","handlingStrategy":"validation","validationCode":"use std::fs;\nuse std::ffi::OsStr;\n\nfn cases_have_utf8_names(cases_dir: &std::path::Path) -> std::io::Result<bool> {\n    for entry in fs::read_dir(cases_dir)? {\n        if entry?.file_name().to_str().is_none() {\n            return Ok(false);\n        }\n    }\n    Ok(true)\n}","typeGuard":"fn is_utf8_name(entry: &std::fs::DirEntry) -> bool {\n    entry.file_name().to_str().is_some()\n}","tryCatchPattern":null,"preventionTips":["Only touch in-progress fixture output directories with UTF-8-safe tooling","Never pipe raw bytes into filenames when cleaning temp files in the cases directory","Run the fixture `verify` command after any manual intervention in the output directory","Keep output directories on filesystems that preserve UTF-8 names reliably (avoid network shares with legacy encodings)"],"tags":["filesystem","fixtures","encoding","cli"],"backgroundTag":"invalid-identifier-format","analyzedSha":"e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8","analyzedAt":"2026-09-13T03:07:16.451Z","contentChangedAt":"2026-09-13T03:07:16.451Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}