AprilNEA/OpenLogi · error
resumable fixture cases contain a non-UTF-8 entry
Error message
resumable fixture cases contain a non-UTF-8 entry
What it means
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.
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
Example fix
// before (shell): stray file with raw-byte name in the resumable output $ ls output/cases/ my-cassette.json '\xff\xfe.tmp' // after: remove or rename the invalid entry, then rerun $ rm output/cases/'\xff\xfe.tmp' $ openlogi fixture contribute ... # resumes cleanly
Defensive patterns
Strategy: validation
Validate before calling
use std::fs;
use std::ffi::OsStr;
fn cases_have_utf8_names(cases_dir: &std::path::Path) -> std::io::Result<bool> {
for entry in fs::read_dir(cases_dir)? {
if entry?.file_name().to_str().is_none() {
return Ok(false);
}
}
Ok(true)
} Type guard
fn is_utf8_name(entry: &std::fs::DirEntry) -> bool {
entry.file_name().to_str().is_some()
} Prevention
- 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)
When it happens
Trigger: 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.
Common situations: 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.
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
- fixture directory has no UTF-8 synthetic ID
- in-progress contribution contains a non-UTF-8 entry
- resumable fixture cases contain unexpected file
- already exists but is not an in-progress OpenLogi…
- in-progress contribution contains unexpected entry
AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13).
Data as JSON: /api/errors/1456652abcaeb7fc.
Report an issue: GitHub.
Appendix: source
Thrown at crates/openlogi-cli/src/cmd/fixture/contribute.rs:310
"in-progress contribution contains unexpected entry {other:?}; refusing to \
publish over it"
),
None => bail!("in-progress contribution contains a non-UTF-8 entry"),
}
}
Ok(())
}
fn validate_resumable_cases(directory: &Path, cassettes: &[HidCassette]) -> Result<()> {
let expected = cassettes
.iter()
.map(|cassette| format!("{}.json", cassette.name))
.collect::<Vec<_>>();
for entry in fs::read_dir(directory).context("could not inspect resumable fixture cases")? {
let entry = entry.context("could not inspect resumable fixture case")?;
let name = entry.file_name();
let Some(name) = name.to_str() else {
bail!("resumable fixture cases contain a non-UTF-8 entry");
};
if !expected.iter().any(|expected| expected == name) {
bail!("resumable fixture cases contain unexpected file {name:?}");
}
require_regular_file(&entry.path(), "fixture cassette")?;
}
Ok(())
}
fn identity_plan(
profile: &DeviceProfile,
selected_route: &DeviceRoute,
) -> Result<HidCassetteIdentityPlan> {
let mut plan = HidCassetteIdentityPlan::default();
let model = match selected_route {
DeviceRoute::Bolt { receiver_uid, slot } => {
plan.insert(
SanitizedIdentityKind::ReceiverUniqueId,View on GitHub (pinned to e846e6f4b4)