AprilNEA/OpenLogi · error

fixture structure verification failed

Error message

fixture structure verification failed: {asset} must be a non-symlink regular file

What it means

`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.

Solutions

  1. Replace the symlink with a real copy of the file's content.
  2. If a directory occupies the expected filename, move its contents and put the actual file there.
  3. Regenerate the asset with the fixture tooling so the correct file type is produced.
  4. Re-run `openlogi fixture verify`.

Example fix

# before: fixtures/bolt/manifest.json -> ../shared/manifest.json (symlink)
# after
rm fixtures/bolt/manifest.json
cp ../shared/manifest.json fixtures/bolt/manifest.json
Defensive patterns

Strategy: validation

Validate before calling

let md = std::fs::symlink_metadata(path)?;
assert!(md.is_file() && !md.file_type().is_symlink(), "fixture asset must be a real file: {}", path.display());

Prevention

When it happens

Trigger: `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.

Common situations: 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.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13). Data as JSON: /api/errors/aedfebe8b9c58bc5. Report an issue: GitHub.

Appendix: source

Thrown at crates/openlogi-cli/src/cmd/fixture/verify.rs:238

    })?;
    if metadata.file_type().is_symlink() || !metadata.is_dir() {
        bail!("fixture structure verification failed: {asset} must be a non-symlink directory");
    }
    Ok(())
}

fn require_entry_directory(entry: &DirEntry, asset: &str) -> Result<()> {
    let metadata = entry_metadata(entry, asset)?;
    if metadata.file_type().is_symlink() || !metadata.is_dir() {
        bail!("fixture structure verification failed: {asset} must be a non-symlink directory");
    }
    Ok(())
}

fn require_regular_file(entry: &DirEntry, asset: &str) -> Result<()> {
    let metadata = entry_metadata(entry, asset)?;
    if metadata.file_type().is_symlink() || !metadata.is_file() {
        bail!("fixture structure verification failed: {asset} must be a non-symlink regular file");
    }
    Ok(())
}

fn entry_metadata(entry: &DirEntry, asset: &str) -> Result<std::fs::Metadata> {
    fs::symlink_metadata(entry.path()).with_context(|| {
        format!("fixture structure verification failed: could not inspect {asset}")
    })
}

fn entry_name(entry: &DirEntry) -> Result<String> {
    entry.file_name().into_string().map_err(|_| {
        anyhow::anyhow!("fixture structure verification failed: fixture paths must be valid UTF-8")
    })
}

#[cfg(test)]
mod tests;

View on GitHub (pinned to e846e6f4b4)