{"record":{"id":"0f46582190def216","repo":"vxcontrol/pentagi","slug":"context-cancelled-while-waiting-for-task-to-start","errorCode":null,"errorMessage":"context cancelled while waiting for task to start. Call %s to check whether a task was created","messagePattern":"context cancelled while waiting for task to start\\. Call (.+?) to check whether a task was created","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"backend/pkg/tools/flow_manager.go","lineNumber":808,"sourceCode":"\t\ttasks, err := t.db.GetFlowTasks(ctx, t.flowID)\n\t\tif err == nil {\n\t\t\tfor _, task := range tasks {\n\t\t\t\tif task.Status == database.TaskStatusRunning || task.Status == database.TaskStatusWaiting {\n\t\t\t\t\treturn fmt.Sprintf(\n\t\t\t\t\t\t\"Input accepted. Task %q (ID: %d) is now running — the generator has produced its subtask plan. \"+\n\t\t\t\t\t\t\t\"Call %s with detail='running' to see what the agent is doing.\",\n\t\t\t\t\t\ttask.Title, task.ID, GetFlowStatusToolName), nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif time.Now().After(deadline) {\n\t\t\tbreak\n\t\t}\n\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn \"\", fmt.Errorf(\n\t\t\t\t\"context cancelled while waiting for task to start. \"+\n\t\t\t\t\t\"Call %s to check whether a task was created\",\n\t\t\t\tGetFlowStatusToolName)\n\t\tcase <-ticker.C:\n\t\t}\n\t}\n\n\treturn fmt.Sprintf(\n\t\t\"Input accepted but no running task appeared within %s. \"+\n\t\t\t\"The generator may still be working. Call %s to check the current state.\",\n\t\tt.pollTimeout, GetFlowStatusToolName), nil\n}\n\n// patchFlowSubtasksTool implements patch_flow_subtasks.\ntype patchFlowSubtasksTool struct {\n\tflowID  int64\n\tdb      database.Querier\n\thandler func(ctx context.Context, taskID int64, patch SubtaskPatch) error","sourceCodeStart":790,"sourceCodeEnd":826,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/flow_manager.go#L790-L826","documentation":"After submit_flow_input successfully delivered input that triggers task creation, waitForTaskReady polls the DB for a running/waiting task. If the caller's context is cancelled during that polling window, the tool aborts with this message. The input was likely delivered, but the tool cannot confirm the generator produced a task — the caller must check flow status.","triggerScenarios":"The parent context (agent run deadline, HTTP request, operator cancel) is cancelled while waitForTaskReady is between poll ticks — e.g. long generator latency exceeding the caller's remaining budget.","commonSituations":"Generator/LLM taking longer than the surrounding request timeout; shutting down the agent mid-poll; a gateway cancelling the request; pollTimeout configured larger than the caller's context deadline.","solutions":["Call get_flow_status to see whether a task was actually created before retrying anything.","If a task exists, do not resubmit input — proceed with the normal flow.","If no task was created and the flow is waiting, resubmit the input with a longer-lived context.","Ensure the caller's context deadline comfortably exceeds pollTimeout (taskReadyPollTimeout) so cancellation does not interrupt the confirmation loop."],"exampleFix":"// before: short-lived request context kills the confirmation poll\nreqCtx := r.Context()\nresult, _ := tool.Handle(reqCtx, \"submit_flow_input\", args)\n// after: decouple from request lifetime\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)\ndefer cancel()\nresult, _ := tool.Handle(ctx, \"submit_flow_input\", args)","handlingStrategy":"try-catch","validationCode":"// Ensure the caller's deadline comfortably exceeds the poll window\nif deadline, ok := ctx.Deadline(); ok && time.Until(deadline) < taskReadyPollTimeout+5*time.Second {\n    ctx, _ = context.WithTimeout(context.Background(), taskReadyPollTimeout+time.Minute)\n}","typeGuard":null,"tryCatchPattern":"_, err := tool.Handle(ctx, \"submit_flow_input\", args)\nif err != nil && strings.Contains(err.Error(), \"context cancelled while waiting\") {\n    // input was likely delivered; confirm via status instead of resubmitting\n    _ = getFlowStatus(ctx)\n}","preventionTips":["Use a context independent of short-lived HTTP requests for flow tools.","Size the caller deadline larger than taskReadyPollTimeout.","Handle SIGTERM shutdowns by letting in-flight submits finish or persisting state.","Never resubmit input after this error until status confirms no task was created."],"tags":["context-cancelled","polling","flow-control"],"backgroundTag":"context-canceled","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}