AprilNEA/OpenLogi · error
already exists but is not an in-progress OpenLogi…
Error message
{} already exists but is not an in-progress OpenLogi contribution; run `openlogi fixture verify {}` to inspect it What it means
`openlogi fixture contribute` resumes an in-progress contribution by looking for a state file (`state.json`-style) inside the `--output` directory. If the output path exists as a directory but has no contribution state file, the command cannot treat it as resumable and bails rather than risk mixing a contribution into unrelated content. This guards against publishing a fixture manifest over an arbitrary directory the user happens to point at.
Solutions
- Run `openlogi fixture verify <output-dir>` as the message suggests to inspect what the directory actually contains.
- If the directory is not meant to be a contribution, choose a fresh (nonexistent) --output path so `contribute` starts from step 1 cleanly.
- If you intended to resume, restore the contribution state file (rerun the first contribute step) or use the original directory where step 1 wrote it.
- If the directory holds unrelated files, move them away and rerun with an empty/new directory.
Example fix
// before openlogi fixture contribute --output ./my-fixture ... // (./my-fixture exists but was not created by `fixture contribute`) // after rm -rf ./my-fixture # or pick a new path openlogi fixture contribute --output ./my-fixture ... // or inspect it first: openlogi fixture verify ./my-fixture
Defensive patterns
Strategy: validation
Validate before calling
const STATE_FILE: &str = "state.json";
async fn ensure_resumable(output: &Path) -> anyhow::Result<()> {
anyhow::ensure!(output.is_dir(), "{} is not a directory", output.display());
anyhow::ensure!(
output.join(STATE_FILE).try_exists()?,
"{} is not an in-progress contribution",
output.display()
);
Ok(())
} Prevention
- Always resume with the exact --output directory the first run printed, not a parent or sibling.
- Never delete or move the state file inside a contribution directory between runs.
- Use a fresh, previously nonexistent directory for each new contribution.
- When in doubt, run `openlogi fixture verify <dir>` before resuming.
When it happens
Trigger: Running `openlogi fixture contribute --output DIR ...` a second time (or with a pre-created DIR) where DIR exists, is a directory, and does not contain the contribution state file written by step 1 — e.g. the directory was created manually, was partially cleaned, or is some other project's directory.
Common situations: Pointing --output at a generic scratch/repo directory instead of the one created by the first contribute run; deleting or moving `state.json` out of the contribution directory; resuming after a crash that corrupted or removed the state file; passing the wrong directory (typo or parent directory).
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- in-progress contribution contains unexpected entry
- in-progress contribution contains a non-UTF-8 entry
- saved contribution profile does not match its resumable…
- resumable fixture cases contain a non-UTF-8 entry
- resumable fixture cases contain unexpected file
AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13).
Data as JSON: /api/errors/b5aaf53048d6c81e.
Report an issue: GitHub.
Appendix: source
Thrown at crates/openlogi-cli/src/cmd/fixture/contribute.rs:73
selected_route: DeviceRoute,
}
pub async fn run(args: ContributeArgs) -> Result<()> {
validate_args(&args)?;
let state_path = args.output.join(STATE_FILE);
if !args
.output
.try_exists()
.context("could not inspect output directory")?
{
return start(args, &state_path).await;
}
require_directory(&args.output, "contribution output")?;
if !state_path
.try_exists()
.context("could not inspect contribution state")?
{
bail!(
"{} already exists but is not an in-progress OpenLogi contribution; run `openlogi \
fixture verify {}` to inspect it",
args.output.display(),
args.output.display()
);
}
finish(args, &state_path).await
}
async fn start(args: ContributeArgs, state_path: &Path) -> Result<()> {
let profile_id = format!("{}-profile", args.id);
println!("Step 1/2: reading semantic state through the running OpenLogi Agent…");
let captured = record_profile::capture_for_contribution(
profile_id.clone(),
args.name.clone(),
args.device.as_deref(),
)
.await?;View on GitHub (pinned to e846e6f4b4)