{"record":{"id":"aedfebe8b9c58bc5","repo":"AprilNEA/OpenLogi","slug":"fixture-structure-verification-failed-asset-must-be-a-non-aedfeb","errorCode":null,"errorMessage":"fixture structure verification failed: {asset} must be a non-symlink regular file","messagePattern":"fixture structure verification failed: (.+?) must be a non-symlink regular file","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/verify.rs","lineNumber":238,"sourceCode":"    })?;\n    if metadata.file_type().is_symlink() || !metadata.is_dir() {\n        bail!(\"fixture structure verification failed: {asset} must be a non-symlink directory\");\n    }\n    Ok(())\n}\n\nfn require_entry_directory(entry: &DirEntry, asset: &str) -> Result<()> {\n    let metadata = entry_metadata(entry, asset)?;\n    if metadata.file_type().is_symlink() || !metadata.is_dir() {\n        bail!(\"fixture structure verification failed: {asset} must be a non-symlink directory\");\n    }\n    Ok(())\n}\n\nfn require_regular_file(entry: &DirEntry, asset: &str) -> Result<()> {\n    let metadata = entry_metadata(entry, asset)?;\n    if metadata.file_type().is_symlink() || !metadata.is_file() {\n        bail!(\"fixture structure verification failed: {asset} must be a non-symlink regular file\");\n    }\n    Ok(())\n}\n\nfn entry_metadata(entry: &DirEntry, asset: &str) -> Result<std::fs::Metadata> {\n    fs::symlink_metadata(entry.path()).with_context(|| {\n        format!(\"fixture structure verification failed: could not inspect {asset}\")\n    })\n}\n\nfn entry_name(entry: &DirEntry) -> Result<String> {\n    entry.file_name().into_string().map_err(|_| {\n        anyhow::anyhow!(\"fixture structure verification failed: fixture paths must be valid UTF-8\")\n    })\n}\n\n#[cfg(test)]\nmod tests;","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/verify.rs#L220-L256","documentation":"`require_regular_file` checks that an expected fixture file entry is a plain regular file, using `symlink_metadata` so symlinks are rejected even when they point at a valid file. Expected manifests, cassettes, and other fixture assets must be real files inside the corpus.","triggerScenarios":"`inspect` or `load_cassettes` calls `require_regular_file` on an entry (e.g. a manifest JSON or cassette JSON) that is a symlink or a directory instead of a regular file.","commonSituations":"A cassette or manifest was replaced by a symlink to shared content; the expected filename actually holds a directory; a tool created a placeholder of the wrong type.","solutions":["Replace the symlink with a real copy of the file's content.","If a directory occupies the expected filename, move its contents and put the actual file there.","Regenerate the asset with the fixture tooling so the correct file type is produced.","Re-run `openlogi fixture verify`."],"exampleFix":"# before: fixtures/bolt/manifest.json -> ../shared/manifest.json (symlink)\n# after\nrm fixtures/bolt/manifest.json\ncp ../shared/manifest.json fixtures/bolt/manifest.json","handlingStrategy":"validation","validationCode":"let md = std::fs::symlink_metadata(path)?;\nassert!(md.is_file() && !md.file_type().is_symlink(), \"fixture asset must be a real file: {}\", path.display());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid symlinking shared manifests/cassettes; duplicate or generate them","Regenerate fixtures with tooling instead of hand-placing files of guessed types","Run `openlogi fixture verify` after any fixture restructuring"],"tags":["fixture","filesystem","symlink","verification"],"backgroundTag":"incompatible-source-type","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"}