vxcontrol/pentagi · error

operation %d: add requires title

Error message

operation %d: add requires title

What it means

SubtaskPatch.Validate checks each SubtaskOperation in the patch. For op == SubtaskOpAdd, both Title and Description are mandatory; this error fires when Title is empty. It protects the task planner from creating unnamed subtasks via the patch_flow_subtasks tool.

Source

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

type WaitFlowCompletionAction struct {
	Timeout Int64  `json:"timeout" jsonschema:"required,type=integer" jsonschema_description:"How long to wait for the running automation task to finish, in seconds. Use 0 or a negative value to apply the default timeout of 60 seconds. Values above 3600 are capped at 3600 seconds (1 hour)."`
	Message string `json:"message" jsonschema:"required,title=Wait message" jsonschema_description:"Engagement-log entry — a 1-2 short sentence running commentary explaining why you are waiting for the automation to finish. Written in the engagement language declared by your system prompt."`
}

// PatchFlowSubtasksAction defines arguments for the patch_flow_subtasks tool.
type PatchFlowSubtasksAction struct {
	TaskID     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'."`
	Operations []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)."`
	Message    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."`
}

// 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)

View on GitHub (pinned to ea665308ba)

Solutions

  1. Set a non-empty title on every add operation before calling Validate/applying the patch.
  2. Pre-validate the operations array client-side and reject add ops missing title or description.
  3. Tighten the tool's JSON schema description/prompt so the LLM always supplies both fields.

Example fix

// before
ops := []SubtaskOperation{{Op: SubtaskOpAdd, Description: "scan ports"}}
// after
ops := []SubtaskOperation{{Op: SubtaskOpAdd, Title: "Port scan", Description: "scan ports"}}
Defensive patterns

Strategy: validation

Validate before calling

for i, op := range ops {
    if op.Op == "add" && (op.Title == "" || op.Description == "") {
        return fmt.Errorf("op %d: add needs title and description", i)
    }
}

Type guard

func validAddOp(op SubtaskOperation) bool {
    return op.Op == SubtaskOpAdd && op.Title != "" && op.Description != ""
}

Try / catch

if err := patch.Validate(); err != nil {
    var idx int
    if _, scanErr := fmt.Sscanf(err.Error(), "operation %d:", &idx); scanErr == nil {
        // repair or drop operations[idx] and revalidate
    }
}

Prevention

When it happens

Trigger: Submitting PatchFlowSubtasksAction with an operations entry {"op":"add"} (or op=add via SubtaskPatch) whose title field is empty or omitted; LLM tool call omitting title in an add operation.

Common situations: LLM agents generate add operations with only a description; JSON marshaling drops an empty title field; hand-written automation scripts building patches.

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/4d538fb374b8e48a. Report an issue: GitHub.