{"record":{"id":"84e86bced6c1d87a","repo":"AprilNEA/OpenLogi","slug":"output-already-exists-pass-force-to-replace-it-after","errorCode":null,"errorMessage":"output {} already exists; pass --force to replace it after validation","messagePattern":"output (.+?) already exists; pass --force to replace it after validation","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/output.rs","lineNumber":12,"sourceCode":"//! Validated fixture-only atomic publication.\n\nuse std::io::Write as _;\nuse std::path::Path;\n\nuse anyhow::{Context, Result, bail};\nuse atomic_write_file::AtomicWriteFile;\nuse serde::Serialize;\n\npub(super) fn ensure_output_available(path: &Path, force: bool) -> Result<()> {\n    if !force && path.try_exists().context(\"could not inspect output path\")? {\n        bail!(\n            \"output {} already exists; pass --force to replace it after validation\",\n            path.display()\n        );\n    }\n    Ok(())\n}\n\npub(super) fn write_json_atomically<T: Serialize>(\n    path: &Path,\n    value: &T,\n    force: bool,\n    asset: &str,\n) -> Result<()> {\n    ensure_output_available(path, force)?;\n    let mut json =\n        serde_json::to_vec_pretty(value).with_context(|| format!(\"could not serialize {asset}\"))?;\n    json.push(b'\\n');\n    if let Some(parent) = path","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/output.rs#L1-L30","documentation":"`ensure_output_available` refuses to overwrite an existing output file unless `--force` is passed. Output JSON files are written atomically (via AtomicWriteFile), but even atomically an existing file is never silently replaced — validation must complete and the operator must explicitly opt in with `--force`.","triggerScenarios":"Any command that writes an output JSON (via write_json_atomically) targets a path that already exists while `force` is false. Also triggered in the test `refuses_existing_files_without_force`.","commonSituations":"Re-running a contribute/generate step whose output file from a previous run still exists; a partially completed earlier attempt left artifacts behind.","solutions":["Re-run the command with `--force` after you have validated the replacement is intended.","Delete or move the existing file first (`rm <path>` or `mv <path> <path>.bak`) and re-run without --force.","Write to a fresh output directory so the id/output naming requirement yields an unused path."],"exampleFix":"// before\nopenlogi fixture contribute finish --id mx-master --name \"MX Master\" ...  # output exists\n// after\nopenlogi fixture contribute finish --id mx-master --name \"MX Master\" ... --force","handlingStrategy":"validation","validationCode":"if [ -e \"$OUT\" ]; then echo \"output exists; pass --force or remove it first\" >&2; exit 1; fi","typeGuard":null,"tryCatchPattern":"match write_outputs() {\n    Err(e) if e.to_string().contains(\"already exists; pass --force\") => {\n        // prompt the user, then retry with force=true after validation\n    }\n    other => other?,\n}","preventionTips":["Clean previous output artifacts before re-running generation.","Only pass --force after reviewing the file that would be replaced.","Use fresh output directories per contribution to avoid collisions."],"tags":["filesystem","output","overwrite"],"backgroundTag":"file-already-exists","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"}