{"record":{"id":"c8f0dd8a35504c71","repo":"risingwavelabs/risingwave","slug":"task-has-been-finished","errorCode":null,"errorMessage":"task {:?} has been finished","messagePattern":"task (.+?) has been finished","errorType":"error_code","errorClass":"BatchError","httpStatus":null,"severity":"error","filePath":"src/batch/src/task/task_execution.rs","lineNumber":679,"sourceCode":"        let task_output = TaskOutput {\n            receiver,\n            output_id: output_id.try_into()?,\n            failure: self.failure.clone(),\n        };\n        Ok(task_output)\n    }\n\n    pub fn check_if_running(&self) -> Result<()> {\n        if *self.state.lock() != TaskStatus::Running {\n            bail!(\"task {:?} is not running\", self.get_task_id());\n        }\n        Ok(())\n    }\n\n    pub fn check_if_aborted(&self) -> Result<bool> {\n        match *self.state.lock() {\n            TaskStatus::Aborted => Ok(true),\n            TaskStatus::Finished => bail!(\"task {:?} has been finished\", self.get_task_id()),\n            _ => Ok(false),\n        }\n    }\n\n    /// Check the task status: whether has ended.\n    pub fn is_end(&self) -> bool {\n        let guard = self.state.lock();\n        !(*guard == TaskStatus::Running || *guard == TaskStatus::Pending)\n    }\n}\n\nimpl BatchTaskExecution {\n    pub(crate) fn set_heartbeat_join_handle(&self, join_handle: JoinHandle<()>) {\n        *self.heartbeat_join_handle.lock() = Some(join_handle);\n    }\n\n    pub(crate) fn heartbeat_join_handle(&self) -> Option<JoinHandle<()>> {\n        self.heartbeat_join_handle.lock().take()","sourceCodeStart":661,"sourceCodeEnd":697,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/batch/src/task/task_execution.rs#L661-L697","documentation":"Raised by BatchTaskExecution::check_if_aborted: when checking whether a task was aborted, the state lock shows TaskStatus::Finished instead, so the check bails with this message. It fires when a cancellation/abort request arrives for a task that already completed successfully before the abort could take effect. The offending input is a task_id whose abort is moot because the task finished first.","triggerScenarios":"Thrown at src/batch/src/task/task_execution.rs:679 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Treat the error as benign in cancellation paths: the goal (no more work) is already achieved when the task finished","Check task status before issuing abort/cancel calls to skip already-finished tasks","Return the task's recorded result/output to the caller instead of the abort attempt's error","Suppress or downgrade this error in client-facing responses when the original request was a cancel"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}