{"record":{"id":"b054561f0c1e1706","repo":"vxcontrol/pentagi","slug":"operation-d-modify-requires-id","errorCode":null,"errorMessage":"operation %d: modify requires id","messagePattern":"operation (.+?): modify requires id","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/args.go","lineNumber":334,"sourceCode":"\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}\n\ntype Bool bool\n\nfunc (b *Bool) UnmarshalJSON(data []byte) error {","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/args.go#L316-L352","documentation":"SubtaskPatch.Validate requires a non-nil ID for SubtaskOpModify; this error fires when a modify operation provides new title/description but omits the target subtask ID.","triggerScenarios":"Patch operation {\"op\":\"modify\",\"title\":\"Renamed\"} without \"id\" submitted via patch_flow_subtasks or SubtaskPatch.Validate.","commonSituations":"LLM rewrites subtask titles without echoing IDs; batch-edit tooling constructs modify ops keyed by index instead of ID.","solutions":["Include the subtask ID (from get_flow_status detail=subtasks) in every modify operation.","Pre-validate and reject modify ops with nil ID before sending the patch.","Fix generation code to carry the ID through when transforming plan entries into ops."],"exampleFix":"// before\nops := []SubtaskOperation{{Op: SubtaskOpModify, Title: \"Renamed\"}}\n// after\nops := []SubtaskOperation{{Op: SubtaskOpModify, ID: int64Ptr(7), Title: \"Renamed\"}}","handlingStrategy":"type-guard","validationCode":"for i, op := range ops {\n    if op.Op == \"modify\" && op.ID == nil {\n        return fmt.Errorf(\"op %d: modify needs id\", i)\n    }\n}","typeGuard":"func modifiableOp(op SubtaskOperation) bool {\n    return op.Op == SubtaskOpModify && op.ID != nil && (op.Title != \"\" || op.Description != \"\")\n}","tryCatchPattern":"if err := patch.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"modify requires id\") {\n        // resolve IDs from the current plan and rebuild the operation\n    }\n}","preventionTips":["Carry the subtask ID through any transformation that builds modify ops.","Resolve plan entries to IDs before editing rather than by position.","Pre-validate modify ops for non-nil ID before calling the tool.","Reject LLM modify ops without IDs and prompt for a retry with IDs."],"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"}