{"record":{"id":"299455c166de4ae9","repo":"BoundaryML/baml","slug":"failed-to-replace-with","errorCode":null,"errorMessage":"failed to replace {} with {}: {}","messagePattern":"failed to replace (.+?) with (.+?): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"baml_language/crates/baml/src/main.rs","lineNumber":1630,"sourceCode":"    let current = PathBuf::from(&args[1]);\n    let mut last_error = None;\n    for _ in 0..60 {\n        std::thread::sleep(Duration::from_millis(250));\n        match fs::remove_file(&current) {\n            Ok(()) => match fs::rename(&tmp, &current) {\n                Ok(()) => return Ok(()),\n                Err(err) => last_error = Some(err),\n            },\n            Err(err) if err.kind() == std::io::ErrorKind::NotFound => {\n                match fs::rename(&tmp, &current) {\n                    Ok(()) => return Ok(()),\n                    Err(err) => last_error = Some(err),\n                }\n            }\n            Err(err) => last_error = Some(err),\n        }\n    }\n    Err(anyhow!(\n        \"failed to replace {} with {}: {}\",\n        current.display(),\n        tmp.display(),\n        last_error\n            .map(|err| err.to_string())\n            .unwrap_or_else(|| \"timed out\".to_string())\n    ))\n}\n\nfn write_text_atomic(path: &Path, text: &str) -> Result<()> {\n    if let Some(parent) = path.parent() {\n        fs::create_dir_all(parent)?;\n    }\n    let tmp = path.with_extension(\"tmp\");\n    fs::write(&tmp, text)?;\n    fs::rename(tmp, path)?;\n    Ok(())\n}","sourceCodeStart":1612,"sourceCodeEnd":1648,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/baml/src/main.rs#L1612-L1648","documentation":"After retrying for up to 60 attempts (~15 seconds) to swap the running executable via the Windows self-update path, `replace_running_exe` gives up and reports the last error (or 'timed out' if all retries failed). The swap typically fails because Windows locks the currently running exe file, preventing rename/replace operations.","triggerScenarios":"Calling `baml --replace <tmp> <current>` on Windows when the target exe is locked by the OS or another process for the full 15-second retry window; permission denied on the target path.","commonSituations":"Antivirus or an installer holds a handle to baml.exe; the CLI is running from a protected directory like Program Files without elevation; multiple baml processes are running simultaneously; the file is on a filesystem that disallows renaming a running binary.","solutions":["Ensure no other baml processes are running (check Task Manager) and retry the update.","Run the update from an elevated (Administrator) prompt if baml.exe is in a protected directory.","Temporarily disable antivirus real-time scanning or add an exclusion for baml.exe, then retry.","As a fallback, manually download the new release and replace baml.exe while the old one is not running."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Rust\nmatch result {\n    Err(e) if e.to_string().contains(\"failed to replace\") => {\n        eprintln!(\"exe swap failed (file locked?): {e}; retry after closing other baml processes or run elevated\");\n    }\n    _ => {}\n}","preventionTips":["Close all running baml processes before updating.","Update from an elevated prompt when the binary lives in a protected directory.","Add antivirus exclusions for the CLI binary path.","Install via a package manager that handles in-use binaries instead of in-place exe swap."],"tags":["cli","self-update","windows","file-locked","timeout"],"backgroundTag":"file-write-failed","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}