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

  1. Delete the empty/leftover cases directory from the fixture folder, then re-verify
  2. Or re-add the intended case entries to the manifest if the fixture was never meant to be profile-only
  3. 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 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


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)