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

  1. Run `openlogi fixture verify <output-dir>` as the message suggests to inspect what the directory actually contains.
  2. If the directory is not meant to be a contribution, choose a fresh (nonexistent) --output path so `contribute` starts from step 1 cleanly.
  3. 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.
  4. 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

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


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)