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
- Set a non-empty title on every add operation before calling Validate/applying the patch.
- Pre-validate the operations array client-side and reject add ops missing title or description.
- 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
- Always emit both title and description for add operations in LLM tool prompts.
- Pre-validate patches client-side before invoking patch_flow_subtasks.
- Set jsonschema required fields so the model is constrained at generation time.
- Drop malformed add ops instead of failing the whole patch when partial application is acceptable.
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
- operation %d: add requires description
- operation %d: remove requires id
- operation %d: modify requires id
- operation %d: modify requires at least title or description
- operation %d: reorder requires id
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/4d538fb374b8e48a.
Report an issue: GitHub.