{"record":{"id":"815f5534a7f8a321","repo":"AprilNEA/OpenLogi","slug":"relationship-verification-failed-fixture-directory-name-must","errorCode":null,"errorMessage":"relationship verification failed: fixture directory name must equal manifest id {fixture_id:?}","messagePattern":"relationship verification failed: fixture directory name must equal manifest id (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/verify.rs","lineNumber":183,"sourceCode":"        bail!(\"relationship verification failed: missing declared fixture case file {missing:?}\");\n    }\n    Ok(found.into_values().collect())\n}\n\nfn case_file_name(case_name: &str) -> Result<String> {\n    if matches!(case_name, \".\" | \"..\") || case_name.contains('/') || case_name.contains('\\\\') {\n        bail!(\n            \"relationship verification failed: fixture case name {case_name:?} is not a safe file name\"\n        );\n    }\n    Ok(format!(\"{case_name}.json\"))\n}\n\nfn require_directory_id(directory: &Path, fixture_id: &str) -> Result<()> {\n    if directory.file_name().and_then(|name| name.to_str()) == Some(fixture_id) {\n        Ok(())\n    } else {\n        bail!(\n            \"relationship verification failed: fixture directory name must equal manifest id {fixture_id:?}\"\n        )\n    }\n}\n\nfn read_json<T: DeserializeOwned>(path: &Path, asset: &str) -> Result<T> {\n    let bytes = fs::read(path).with_context(|| {\n        format!(\n            \"fixture structure verification failed: could not read {asset} {}\",\n            path.display()\n        )\n    })?;\n    serde_json::from_slice(&bytes)\n        .with_context(|| format!(\"schema verification failed while parsing {asset}\"))\n}\n\nfn read_directory(directory: &Path, asset: &str) -> Result<Vec<DirEntry>> {\n    let mut entries = fs::read_dir(directory)","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/verify.rs#L165-L201","documentation":"`require_directory_id` enforces the fixture-layout invariant that the directory name of a fixture must equal the `id` declared in its manifest. When the on-disk directory name and the manifest id diverge, relationship verification fails because cross-references between fixtures would resolve to the wrong directory.","triggerScenarios":"Running `openlogi fixture verify` (`load` -> `require_directory_id`) on a fixture directory whose `file_name()` differs from the manifest's `id` string — e.g. the directory was renamed but the manifest id was not updated, or vice versa.","commonSituations":"Renaming a fixture folder without editing the manifest (or renaming the id without renaming the folder); a merge or copy created a directory named differently from its manifest; a typo introduced during a new fixture's creation.","solutions":["Rename the fixture directory to exactly the manifest `id` value.","Alternatively, update the manifest `id` to match the existing directory name, fixing any cross-references to the old id.","Fix any relationship metadata in other fixtures that points at the old id.","Re-run `openlogi fixture verify`."],"exampleFix":"// before (manifest)\nid = \"bolt-dpi\"\n// directory: bolt_dpi/\n// after\nmv bolt_dpi bolt-dpi   # directory name now equals manifest id","handlingStrategy":"validation","validationCode":"let id: String = toml::from_str::<Manifest>(&std::fs::read_to_string(dir.join(\"manifest.toml\"))?)?.id;\nassert_eq!(dir.file_name().unwrap().to_str(), Some(id.as_str()), \"dir name must equal manifest id\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Rename the directory and the manifest id in the same commit","Scaffold new fixtures with the official tooling so id and directory are generated together","Add a repo-wide grep/CI check comparing every fixture dir name to its manifest id"],"tags":["fixture","manifest","naming","verification"],"backgroundTag":"schema-validation-failed","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"}