{"record":{"id":"eed7678bfdd93e1a","repo":"vxcontrol/pentagi","slug":"task-id-must-be-a-positive-integer","errorCode":null,"errorMessage":"task_id must be a positive integer","messagePattern":"task_id must be a positive integer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/flow_manager.go","lineNumber":844,"sourceCode":"\thandler func(ctx context.Context, taskID int64, patch SubtaskPatch) error\n}\n\nfunc NewPatchFlowSubtasksTool(\n\tflowID int64,\n\tdb database.Querier,\n\thandler func(ctx context.Context, taskID int64, patch SubtaskPatch) error,\n) *patchFlowSubtasksTool {\n\treturn &patchFlowSubtasksTool{flowID: flowID, db: db, handler: handler}\n}\n\nfunc (t *patchFlowSubtasksTool) Handle(ctx context.Context, name string, args json.RawMessage) (string, error) {\n\tvar action PatchFlowSubtasksAction\n\tif err := json.Unmarshal(args, &action); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to parse patch_flow_subtasks args: %w\", err)\n\t}\n\n\tif action.TaskID <= 0 {\n\t\treturn \"\", fmt.Errorf(\"task_id must be a positive integer\")\n\t}\n\n\t// Validate flow is not running\n\ttasks, err := t.db.GetFlowTasks(ctx, t.flowID)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to check flow status: %w\", err)\n\t}\n\n\tfor _, task := range tasks {\n\t\tif task.Status == database.TaskStatusRunning {\n\t\t\treturn \"\", stateGuard(fmt.Errorf(\n\t\t\t\t\"task %q (ID: %d) is currently running; \"+\n\t\t\t\t\t\"patching is not allowed while a task is executing. \"+\n\t\t\t\t\t\"Call %s first, then retry %s\",\n\t\t\t\ttask.Title, task.ID, StopFlowToolName, PatchFlowSubtasksToolName))\n\t\t}\n\t}\n","sourceCodeStart":826,"sourceCodeEnd":862,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/flow_manager.go#L826-L862","documentation":"patch_flow_subtasks requires a positive integer task_id; the parsed action had task_id <= 0 (missing or non-positive). This is an argument-validation guard executed after JSON parsing succeeds but before any database access.","triggerScenarios":"Calling patch_flow_subtasks with task_id omitted (defaults to 0) or explicitly 0/negative — typically when the LLM doesn't know the real task ID and emits a placeholder.","commonSituations":"LLM guessing a task_id because it never fetched the plan; template calls left with default values; client code passing an unset int64 field.","solutions":["Call get_flow_status with detail='tasks' to obtain valid task IDs.","Resend patch_flow_subtasks with the real positive task_id.","If the LLM keeps guessing, include the task list in its context before the patch call."],"exampleFix":"// before\n{\"task_id\": 0, \"operations\": [...]}\n// after: fetch IDs first, then\n{\"task_id\": 17, \"operations\": [...]}","handlingStrategy":"validation","validationCode":"if taskID <= 0 {\n    return errors.New(\"refusing to patch: fetch a valid task_id via get_flow_status detail='tasks' first\")\n}","typeGuard":"func hasValidTaskID(args json.RawMessage) bool {\n    var a struct { TaskID int64 `json:\"task_id\"` }\n    if json.Unmarshal(args, &a) != nil { return false }\n    return a.TaskID > 0\n}","tryCatchPattern":"if _, err := tool.Handle(ctx, \"patch_flow_subtasks\", args); err != nil &&\n    strings.Contains(err.Error(), \"task_id must be a positive integer\") {\n    // refresh known task IDs and rebuild args\n    args = buildArgsFromStatus(getFlowStatus(ctx))\n}","preventionTips":["Always fetch task IDs via get_flow_status before patching.","Never send placeholder/default zero IDs.","Include the current task list in the LLM's context when it plans a patch.","Validate IDs client-side before dispatching the tool call."],"tags":["validation","tool-arguments","flow-control"],"backgroundTag":"invalid-argument","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}