AprilNEA/OpenLogi · error
relationship verification failed: profile-only fixture has…
Error message
relationship verification failed: profile-only fixture has an undeclared cases directory
What it means
`load_cassettes` enforces the relationship between the manifest and the fixture layout: a profile-only fixture (no declared cases) must not have a cases directory on disk. If the manifest declares no cases but a cases directory entry was found during inspection, this bail fires. It throws because a cases directory without declared cases indicates a fixture exported in the wrong mode or a manifest that lost its case list.
Solutions
- Delete the empty/leftover cases directory from the fixture folder, then re-verify
- Or re-add the intended case entries to the manifest if the fixture was never meant to be profile-only
- Re-export the fixture with the correct mode (profile vs cases) using the recording tooling
Example fix
// before fixture-dir/ manifest.toml // cases = [] cases/ // undeclared for profile-only fixture // after fixture-dir/ manifest.toml // cases = []
Defensive patterns
Strategy: validation
Validate before calling
# profile-only fixture must have no cases directory [ -d fixture-dir/cases ] && [ ! -s cases-list ] && echo "remove cases/ or declare cases in the manifest"
Try / catch
match load(fixture_dir) {
Err(e) if e.to_string().contains("profile-only fixture has an undeclared cases directory") => {
remove_dir_all(fixture_dir.join(CASES_DIRECTORY)); // leftover storage
load(fixture_dir)
}
other => other,
} Prevention
- When converting a cases fixture to profile-only, delete the cases directory too
- Record profile-only fixtures into a fresh directory instead of overwriting an old one
- Run verify after any manual manifest edit
When it happens
Trigger: Verifying/loading a fixture whose manifest has an empty `cases` list while the directory contains a recognized cases-directory entry (CASES_DIRECTORY), i.e. profile-only mode with leftover cassette storage.
Common situations: Recording a profile-only fixture over a previous multi-case fixture and the old `cases/` folder was left behind; manually stripping cases from a manifest without deleting the directory; using a profile fixture template that accidentally includes the cases directory.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- relationship verification failed: undeclared fixture case…
- relationship verification failed: missing declared fixture…
- relationship verification failed: fixture directory name…
- fixture structure verification failed: unexpected entry
- relationship verification failed: fixture case names map to…
AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13).
Data as JSON: /api/errors/d8df3a665096690e.
Report an issue: GitHub.
Appendix: source
Thrown at crates/openlogi-cli/src/cmd/fixture/verify.rs:137
})
}
}
fn load_cassettes(
cases_directory: Option<&Path>,
manifest: &FixtureManifest,
) -> Result<Vec<HidCassette>> {
let mut expected = BTreeMap::new();
for case in &manifest.cases {
let file_name = case_file_name(&case.name)?;
if expected.insert(file_name, case.name.as_str()).is_some() {
bail!("relationship verification failed: fixture case names map to the same file");
}
}
if expected.is_empty() {
if cases_directory.is_some() {
bail!(
"relationship verification failed: profile-only fixture has an undeclared cases directory"
);
}
return Ok(Vec::new());
}
let directory = cases_directory.context(
"relationship verification failed: manifest declares cases but the cases directory is missing",
)?;
let mut found = BTreeMap::new();
for entry in read_directory(directory, "fixture cases directory")? {
require_regular_file(&entry, "fixture cassette")?;
let file_name = entry_name(&entry)?;
let Some(case_name) = expected.get(&file_name) else {
bail!("relationship verification failed: undeclared fixture case file {file_name:?}");
};
let cassette: HidCassette = read_json(&entry.path(), "HID cassette")?;
if cassette.name != *case_name {View on GitHub (pinned to e846e6f4b4)