AprilNEA/OpenLogi · error
must be a non-symlink regular file
Error message
{asset} must be a non-symlink regular file What it means
`require_regular_file` demands that an asset path be a plain regular file and not a symlink, using `symlink_metadata` so a symlink is rejected even if it targets a regular file. Fixture integrity checks refuse linked files because their content could silently change with the link target.
Solutions
- Replace the symlink with a real copy: `rm <asset> && cp <target> <asset>`.
- Regenerate the fixture so the file is written in place rather than linked.
- Check before running: `[ -f <asset> ] && [ ! -L <asset> ]`.
Example fix
// before ln -s ../../common/manifest.json out/mx-master/manifest.json // after cp ../../common/manifest.json out/mx-master/manifest.json
Defensive patterns
Strategy: validation
Validate before calling
[ -f "$ASSET" ] && [ ! -L "$ASSET" ] || { echo "$ASSET must be a regular non-symlink file" >&2; exit 1; } Prevention
- Copy fixture files into place rather than symlinking templates.
- Exclude fixture dirs from dotfile/symlink managers.
- Run `find fixtures -type l` in CI to catch links early.
When it happens
Trigger: finish, validate_resumable_layout, or validate_resumable_cases inspects an asset file that is a symlink, or is not a regular file (a directory or missing path — missing paths surface via the `could not inspect {asset}` context instead).
Common situations: Dotfile-style setups that symlink fixture JSON into a shared repo; generating fixture files as symlinks to templates; case files hard-linked/symlinked between fixtures.
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
- must be a non-symlink directory
- output must not be a symlink
- fixture structure verification failed
- fixture structure verification failed
- already exists but is not an in-progress OpenLogi…
AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13).
Data as JSON: /api/errors/32b0987373fbab35.
Report an issue: GitHub.
Appendix: source
Thrown at crates/openlogi-cli/src/cmd/fixture/contribute.rs:495
fn read_json<T: serde::de::DeserializeOwned>(path: &Path, asset: &str) -> Result<T> {
let bytes = fs::read(path).with_context(|| format!("could not read {asset}"))?;
serde_json::from_slice(&bytes).with_context(|| format!("could not parse {asset}"))
}
fn require_directory(path: &Path, asset: &str) -> Result<()> {
let metadata =
fs::symlink_metadata(path).with_context(|| format!("could not inspect {asset}"))?;
if metadata.file_type().is_symlink() || !metadata.is_dir() {
bail!("{asset} must be a non-symlink directory");
}
Ok(())
}
fn require_regular_file(path: &Path, asset: &str) -> Result<()> {
let metadata =
fs::symlink_metadata(path).with_context(|| format!("could not inspect {asset}"))?;
if metadata.file_type().is_symlink() || !metadata.is_file() {
bail!("{asset} must be a non-symlink regular file");
}
Ok(())
}
fn reject_symlink(path: &Path, asset: &str) -> Result<()> {
match fs::symlink_metadata(path) {
Ok(metadata) if metadata.file_type().is_symlink() => {
bail!("{asset} output must not be a symlink")
}
Ok(_) => Ok(()),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(()),
Err(error) => Err(error).with_context(|| format!("could not inspect {asset} output")),
}
}
#[cfg(test)]
mod tests {
use openlogi_fixture::CANONICAL_DEVICE_PROFILE_JSON;View on GitHub (pinned to e846e6f4b4)