vxcontrol/pentagi · error

operation %d: modify requires id

Error message

operation %d: modify requires id

What it means

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.

Source

Thrown at backend/pkg/tools/args.go:334

// ValidateSubtaskPatch validates the operations in a SubtaskPatch
func (sp SubtaskPatch) Validate() error {
	for i, op := range sp.Operations {
		switch op.Op {
		case SubtaskOpAdd:
			if op.Title == "" {
				return fmt.Errorf("operation %d: add requires title", i)
			}
			if op.Description == "" {
				return fmt.Errorf("operation %d: add requires description", i)
			}
		case SubtaskOpRemove:
			if op.ID == nil {
				return fmt.Errorf("operation %d: remove requires id", i)
			}
		case SubtaskOpModify:
			if op.ID == nil {
				return fmt.Errorf("operation %d: modify requires id", i)
			}
			if op.Title == "" && op.Description == "" {
				return fmt.Errorf("operation %d: modify requires at least title or description", i)
			}
		case SubtaskOpReorder:
			if op.ID == nil {
				return fmt.Errorf("operation %d: reorder requires id", i)
			}
		default:
			return fmt.Errorf("operation %d: unknown operation type %q", i, op.Op)
		}
	}
	return nil
}

type Bool bool

func (b *Bool) UnmarshalJSON(data []byte) error {

View on GitHub (pinned to ea665308ba)

Solutions

  1. Include the subtask ID (from get_flow_status detail=subtasks) in every modify operation.
  2. Pre-validate and reject modify ops with nil ID before sending the patch.
  3. Fix generation code to carry the ID through when transforming plan entries into ops.

Example fix

// before
ops := []SubtaskOperation{{Op: SubtaskOpModify, Title: "Renamed"}}
// after
ops := []SubtaskOperation{{Op: SubtaskOpModify, ID: int64Ptr(7), Title: "Renamed"}}
Defensive patterns

Strategy: type-guard

Validate before calling

for i, op := range ops {
    if op.Op == "modify" && op.ID == nil {
        return fmt.Errorf("op %d: modify needs id", i)
    }
}

Type guard

func modifiableOp(op SubtaskOperation) bool {
    return op.Op == SubtaskOpModify && op.ID != nil && (op.Title != "" || op.Description != "")
}

Try / catch

if err := patch.Validate(); err != nil {
    if strings.Contains(err.Error(), "modify requires id") {
        // resolve IDs from the current plan and rebuild the operation
    }
}

Prevention

When it happens

Trigger: Patch operation {"op":"modify","title":"Renamed"} without "id" submitted via patch_flow_subtasks or SubtaskPatch.Validate.

Common situations: LLM rewrites subtask titles without echoing IDs; batch-edit tooling constructs modify ops keyed by index instead of ID.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/b054561f0c1e1706. Report an issue: GitHub.