{"record":{"id":"0f4252ced3ddbd58","repo":"vxcontrol/pentagi","slug":"operation-d-remove-requires-id","errorCode":null,"errorMessage":"operation %d: remove requires id","messagePattern":"operation (.+?): remove requires id","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/args.go","lineNumber":330,"sourceCode":"\tTaskID     int64              `json:\"task_id\" jsonschema:\"required,type=integer\" jsonschema_description:\"ID of the task whose subtask plan to modify. Obtain this from get_flow_status with detail='tasks'.\"`\n\tOperations []SubtaskOperation `json:\"operations\" jsonschema:\"required\" jsonschema_description:\"Delta operations to apply: add (insert new subtask at a position), remove (delete by ID), modify (update title/description), reorder (move to different position). Empty array returns the current plan unchanged. Each operation's title/description, when present, is an engagement-log plan entry (see operations).\"`\n\tMessage    string             `json:\"message\" jsonschema:\"required,title=Patch summary\" jsonschema_description:\"Engagement-log entry — a 1-2 short sentence running commentary describing what changes are being made to the plan. Written in the engagement language declared by your system prompt.\"`\n}\n\n// ValidateSubtaskPatch validates the operations in a SubtaskPatch\nfunc (sp SubtaskPatch) Validate() error {\n\tfor i, op := range sp.Operations {\n\t\tswitch op.Op {\n\t\tcase SubtaskOpAdd:\n\t\t\tif op.Title == \"\" {\n\t\t\t\treturn fmt.Errorf(\"operation %d: add requires title\", i)\n\t\t\t}\n\t\t\tif op.Description == \"\" {\n\t\t\t\treturn fmt.Errorf(\"operation %d: add requires description\", i)\n\t\t\t}\n\t\tcase SubtaskOpRemove:\n\t\t\tif op.ID == nil {\n\t\t\t\treturn fmt.Errorf(\"operation %d: remove requires id\", i)\n\t\t\t}\n\t\tcase SubtaskOpModify:\n\t\t\tif op.ID == nil {\n\t\t\t\treturn fmt.Errorf(\"operation %d: modify requires id\", i)\n\t\t\t}\n\t\t\tif op.Title == \"\" && op.Description == \"\" {\n\t\t\t\treturn fmt.Errorf(\"operation %d: modify requires at least title or description\", i)\n\t\t\t}\n\t\tcase SubtaskOpReorder:\n\t\t\tif op.ID == nil {\n\t\t\t\treturn fmt.Errorf(\"operation %d: reorder requires id\", i)\n\t\t\t}\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"operation %d: unknown operation type %q\", i, op.Op)\n\t\t}\n\t}\n\treturn nil\n}","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/args.go#L312-L348","documentation":"SubtaskPatch.Validate requires a non-nil ID for SubtaskOpRemove; this error fires when a remove operation has no ID pointer set. Without an ID the service cannot know which subtask to delete.","triggerScenarios":"Patch operation {\"op\":\"remove\"} without \"id\", produced by patch_flow_subtasks tool calls or programmatic SubtaskPatch construction.","commonSituations":"LLM attempting to 'remove the last subtask' without looking up its ID first; JSON where id was null; scripts copying add-shaped ops into remove ops.","solutions":["Fetch the current plan (get_flow_status detail=subtasks) and copy the exact subtask ID into the remove operation.","Guard in code: skip remove ops whose ID is nil, or resolve IDs before validation.","Improve the tool prompt so the agent always includes the numeric subtask id for remove."],"exampleFix":"// before\nops := []SubtaskOperation{{Op: SubtaskOpRemove}}\n// after\nops := []SubtaskOperation{{Op: SubtaskOpRemove, ID: int64Ptr(42)}}","handlingStrategy":"type-guard","validationCode":"for i, op := range ops {\n    if op.Op == \"remove\" && op.ID == nil {\n        return fmt.Errorf(\"op %d: remove needs id\", i)\n    }\n}","typeGuard":"func removableOp(op SubtaskOperation) bool {\n    return op.Op == SubtaskOpRemove && op.ID != nil\n}","tryCatchPattern":"if err := patch.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"remove requires id\") {\n        // refetch plan, map titles to IDs, rebuild the patch\n    }\n}","preventionTips":["Fetch current subtask IDs (get_flow_status detail=subtasks) before composing remove ops.","Never build remove operations from title/index alone.","Constrain the tool schema so id is clearly required for remove.","Filter nil-ID remove ops out of LLM output before validation."],"tags":["validation","tool-args","subtasks"],"backgroundTag":"missing-required-argument","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}