{"record":{"id":"6b97b57089227b3e","repo":"risingwavelabs/risingwave","slug":"cannot-create-a-duplicate-task-with-the-same-id","errorCode":null,"errorMessage":"cannot create a duplicate task with the same ID: {:?}","messagePattern":"cannot create a duplicate task with the same ID: (.+?)","errorType":"error_code","errorClass":"BatchError","httpStatus":null,"severity":"error","filePath":"src/batch/src/task/task_manager.rs","lineNumber":144,"sourceCode":"        let task_id = task.get_task_id().clone();\n        let task = Arc::new(task);\n        // Here the task id insert into self.tasks is put in front of `.async_execute`, cuz when\n        // send `TaskStatus::Running` in `.async_execute`, the query runner may schedule next stage,\n        // it's possible do not found parent task id in theory.\n        let ret = if let hash_map::Entry::Vacant(e) = self.tasks.lock().entry(task_id.clone()) {\n            e.insert(task.clone());\n\n            let this = self.clone();\n            let task_id = task_id.clone();\n            let state_reporter = state_reporter.clone();\n            let heartbeat_join_handle = self.runtime.spawn(async move {\n                this.start_task_heartbeat(state_reporter, task_id).await;\n            });\n            task.set_heartbeat_join_handle(heartbeat_join_handle);\n\n            Ok(())\n        } else {\n            bail!(\n                \"cannot create a duplicate task with the same ID: {:?}\",\n                task_id,\n            );\n        };\n        task.async_execute(Some(state_reporter), tracing_context, expr_context)\n            .await\n            .inspect_err(|_| {\n                self.cancel_task(&task_id.to_prost());\n            })?;\n        ret\n    }\n\n    #[cfg(test)]\n    async fn fire_task_for_test(\n        self: &Arc<Self>,\n        tid: &PbTaskId,\n        plan: PlanFragment,\n    ) -> Result<()> {","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/batch/src/task/task_manager.rs#L126-L162","documentation":"A duplicate-key validation guard in TaskManager::fire_task: before spawning a batch task it inserts into the tasks map, and if a TaskId equal to the incoming one is already present the insert fails with this error. TaskIds embed query/stage/epoch identifiers and should be unique per (query, stage, epoch), so a collision means the same task was fired twice — a scheduler retry bug, a duplicate gRPC CreateTask, or an epoch reuse in the meta service.","triggerScenarios":"Thrown at src/batch/src/task/task_manager.rs:144 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Make task creation idempotent: if the existing task has the same identity, return the already-running task instead of erroring","Ensure the scheduler does not re-send CreateTask for the same (query_id, stage_id, epoch) after a timeout without first checking task status","Check meta-node epoch allocation if epochs are being reused across retries","Log both the existing and incoming task contexts to diagnose whether the duplicate came from a retry or a client bug"],"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-14T11:17:12.474Z"}