{"record":{"id":"e7053a8b76e8b27f","repo":"Hmbown/CodeWhale","slug":"failed-to-promote-staged-task-promote-err","errorCode":null,"errorMessage":"Failed to promote staged task {}: {promote_err}","messagePattern":"Failed to promote staged task (.+?): (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/task_manager.rs","lineNumber":1333,"sourceCode":"                        \"failed to remove ignored staged task after queue write failure\"\n                    );\n                }\n                return Err(err);\n            }\n            if let Err(promote_err) = fs::rename(&staged_task_path, &task_path) {\n                let rollback_error = self.persist_queue_locked(&state.queue).err();\n                let cleanup_error = fs::remove_file(&staged_task_path).err();\n                let mut message =\n                    format!(\"Failed to promote staged task {}: {promote_err}\", task.id);\n                if let Some(rollback_error) = rollback_error {\n                    message.push_str(&format!(\"; queue rollback also failed: {rollback_error:#}\"));\n                }\n                if let Some(cleanup_error) = cleanup_error {\n                    message.push_str(&format!(\n                        \"; ignored staged-file cleanup also failed: {cleanup_error}\"\n                    ));\n                }\n                bail!(message);\n            }\n            state.queue = next_queue;\n            state.tasks.insert(task.id.clone(), task.clone());\n        }\n        self.notify.notify_one();\n        Ok(task)\n    }\n\n    /// List tasks, newest first.\n    pub async fn list_tasks(&self, limit: Option<usize>) -> Vec<TaskSummary> {\n        self.list_tasks_scoped(limit, None).await\n    }\n\n    /// List tasks, newest first, optionally scoped to a workspace.\n    pub async fn list_tasks_scoped(\n        &self,\n        limit: Option<usize>,\n        workspace: Option<&Path>,","sourceCodeStart":1315,"sourceCodeEnd":1351,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/task_manager.rs#L1315-L1351","documentation":"The final step of the staged task-create transaction failed: atomically renaming tasks/.<id>.json.pending to tasks/<id>.json (the promote) returned an error. On failure the code rolls the queue back to its previous persisted state and deletes the staged file; if those cleanup operations also fail, their errors are appended to the message ('queue rollback also failed', 'ignored staged-file cleanup also failed').","triggerScenarios":"Filesystem-level promote failure: disk full, permission changed on tasks_dir between staging and rename, the directory removed underneath the process, or antivirus/monitor renaming the file. The appended rollback errors mean the queue file or .pending debris could not be restored either.","commonSituations":"Disk exhaustion while creating tasks; tasks dir on a network mount that went away; sandboxed environments that deny rename; two instances pointed at the same tasks_dir.","solutions":["Check disk space and write permission on the tasks directory; free space or fix ownership, then retry with a new id.","If the message includes 'queue rollback also failed', compare queue state on disk with the running instance; prefer restarting the app in that directory over manually editing the queue.","Remove a leftover .<id>.json.pending only after confirming tasks/<id>.json does not exist, then re-create the task with a fresh id.","Ensure only one process owns a tasks_dir; concurrent writers make promotes and rollbacks interleave."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-flight the exact operations the promote needs:\nfn can_promote(tasks_dir: &Path) -> bool {\n    let probe = tasks_dir.join(format!(\".probe.{}.pending\", std::process::id()));\n    let ok = fs::write(&probe, b\"\").is_ok() && fs::rename(&probe, tasks_dir.join(\".probe.json\")).is_ok();\n    let _ = fs::remove_file(tasks_dir.join(\".probe.json\"));\n    ok\n}","typeGuard":null,"tryCatchPattern":"match tm.add_task_with_id(req, id).await {\n    Err(e) if e.to_string().starts_with(\"Failed to promote staged task\") => {\n        // inspect disk space / perms, then retry ONCE with a new id;\n        // if the message contains 'queue rollback also failed', restart the app instead\n        retry_with_fresh_id(req).await\n    }\n    other => other,\n}","preventionTips":["Monitor free disk space where the tasks dir lives; promotes fail when the FS is full.","Watch for the 'queue rollback also failed' suffix: it means durable state may be inconsistent and a restart is safer than another write.","Keep the tasks dir on a local filesystem; network mounts make rename-based transactions fragile."],"tags":["task","filesystem","atomic-write","crash-recovery","rust"],"backgroundTag":"atomic-write-failure","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}