{"record":{"id":"e7652845b9d397ab","repo":"BigPizzaV3/CodexPlusPlus","slug":"invalid-native-cleanup-receipt","errorCode":null,"errorMessage":"Invalid native cleanup receipt","messagePattern":"Invalid native cleanup receipt","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/native_browser.rs","lineNumber":782,"sourceCode":"    options.read(true).write(true);\n    #[cfg(windows)]\n    {\n        use std::os::windows::fs::OpenOptionsExt;\n        options.share_mode(0x1 | 0x2).custom_flags(0x00200000);\n    }\n    let mut file = match options.open(&path) {\n        Ok(file) => file,\n        Err(error) if error.kind() == std::io::ErrorKind::NotFound => {\n            return verify_restored_state(paths);\n        }\n        Err(error) => return Err(error.into()),\n    };\n    plain_path(&path)?;\n    let deadline = std::time::Instant::now() + timeout;\n    loop {\n        match file.try_lock_exclusive() {\n            Ok(()) => {\n                ensure!(file.metadata()?.len() <= 1024, \"Invalid native cleanup receipt\");\n                file.seek(SeekFrom::Start(0))?;\n                let mut bytes = Vec::new();\n                Read::by_ref(&mut file).take(1025).read_to_end(&mut bytes)?;\n                let receipt: MonitorReceipt = serde_json::from_slice(&bytes)?;\n                ensure!(\n                    receipt.schema == 1 && uuid::Uuid::parse_str(&receipt.generation).is_ok()\n                        && receipt.state == \"restored\",\n                    \"Native browser cleanup did not complete successfully\"\n                );\n                return Ok(());\n            }\n            Err(error) if error.kind() == fs2::lock_contended_error().kind() => {\n                ensure!(\n                    std::time::Instant::now() < deadline,\n                    \"Native browser cleanup is still running; launcher was not terminated\"\n                );\n                std::thread::sleep(Duration::from_millis(50).min(\n                    deadline.saturating_duration_since(std::time::Instant::now()),","sourceCodeStart":764,"sourceCodeEnd":800,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/crates/codex-plus-core/src/native_browser.rs#L764-L800","documentation":"wait_for_monitor_shutdown_at polls monitor.lock until the previous monitor process releases its exclusive lock (meaning cleanup finished). Once the lock is acquired, it validates the cleanup receipt written there: the file must be at most 1024 bytes. This error means the lock was free but the receipt file is larger than the allowed 1024 bytes, so it cannot be a valid MonitorReceipt and the library refuses to trust it.","triggerScenarios":"Calling wait_for_monitor_shutdown (Windows) after monitor cleanup when monitor.lock contains more than 1024 bytes — e.g. a corrupted/oversized receipt, garbage appended by another process, repeated writes without truncation, or the file was overwritten by an unrelated tool.","commonSituations":"A crashed monitor writing a partial/oversized receipt; disk corruption; another process appending to monitor.lock; a user or script editing the lock file; version mismatch where an older/newer build wrote a different format.","solutions":["Confirm the size: `ls -l <state_root>/monitor.lock` (or `dir` on Windows); anything over 1024 bytes is invalid.","Delete the corrupt monitor.lock and let the next monitor run recreate it with a fresh receipt.","Check the diagnostic log (native_browser.compatibility entries) to find which generation/process wrote the oversized file.","Ensure all CodexPlusPlus processes/builds on the machine use the same version so receipt format matches."],"exampleFix":"// before: oversized receipt\n$ ls -l monitor.lock ; -rw-r--r-- 4096 monitor.lock\n// after\nrm monitor.lock && rerun monitor start  # fresh 1024-byte-capped receipt","handlingStrategy":"try-catch","validationCode":"let lock = state_root.join(\"monitor.lock\");\nif let Ok(meta) = std::fs::metadata(&lock) {\n    if meta.len() > 1024 {\n        // receipt is oversized/corrupt: delete monitor.lock and rerun cleanup before waiting\n    }\n}","typeGuard":"fn receipt_size_plausible(p: &std::path::Path) -> bool {\n    std::fs::metadata(p).map(|m| m.len() <= 1024).unwrap_or(false)\n}","tryCatchPattern":"match wait_for_monitor_shutdown(Duration::from_secs(30)) {\n    Err(e) if e.to_string().contains(\"Invalid native cleanup receipt\") => {\n        // treat receipt as corrupt: remove monitor.lock, restore service files from backups, retry\n    }\n    other => other?,\n}","preventionTips":["Never write to or append to monitor.lock outside the library","Shut down monitors through the library's own cleanup path so receipts are truncated properly","Monitor file sizes in the state dir; an oversized monitor.lock indicates corruption early"],"tags":["filesystem","lock-file","validation","corruption"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}