{"record":{"id":"5f8762b1c9032fcf","repo":"can1357/oh-my-pi","slug":"objective-is-required-when-op-create-5f8762","errorCode":null,"errorMessage":"objective is required when op=create","messagePattern":"objective is required when op=create","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/goals/tools/goal-tool.ts","lineNumber":49,"sourceCode":"export function buildGoalToolResponse(\n\tgoal: Goal | null | undefined,\n\toptions?: { includeCompletionReport?: boolean },\n): GoalToolResponse {\n\tconst resolvedGoal = goal ?? null;\n\treturn {\n\t\tgoal: resolvedGoal,\n\t\tremainingTokens: remainingTokens(resolvedGoal),\n\t\tcompletionBudgetReport:\n\t\t\toptions?.includeCompletionReport && resolvedGoal?.status === \"complete\"\n\t\t\t\t? completionBudgetReport(resolvedGoal)\n\t\t\t\t: null,\n\t};\n}\n\nfunction validateCreateParams(params: GoalToolInput): { objective: string; tokenBudget?: number } {\n\tconst objective = params.objective?.trim();\n\tif (!objective) {\n\t\tthrow new ToolError(\"objective is required when op=create\");\n\t}\n\tconst tokenBudget = params.token_budget;\n\tif (tokenBudget !== undefined && (!Number.isInteger(tokenBudget) || tokenBudget <= 0)) {\n\t\tthrow new ToolError(\"token_budget must be a positive integer when provided\");\n\t}\n\treturn { objective, tokenBudget };\n}\n\nexport class GoalTool implements AgentTool<typeof goalSchema, GoalToolDetails> {\n\treadonly name = \"goal\";\n\treadonly label = \"Goal\";\n\treadonly description = prompt.render(goalDescription);\n\treadonly parameters = goalSchema;\n\treadonly strict = true;\n\treadonly intent = \"omit\" as const;\n\treadonly #session: ToolSession;\n\n\tconstructor(session: ToolSession) {","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/goals/tools/goal-tool.ts#L31-L67","documentation":"GoalTool's create operation requires an `objective` string. validateCreateParams trims params.objective and throws this ToolError when it is empty, whitespace-only, or undefined. The tool refuses to create a goal without a stated objective.","triggerScenarios":"Calling the `goal` tool with op=\"create\" and omitting `objective`, passing `objective: \"\"` or `objective: \"   \"` (whitespace-only), or passing a non-string that trims to nothing.","commonSituations":"An LLM agent emits a goal-create tool call but leaves out the objective field; programmatic tool invocations build the params object without the required field; templates copy an update/status call shape (no objective needed) and reuse it for create.","solutions":["Pass a non-empty `objective` string in the tool input, e.g. {\"op\":\"create\",\"objective\":\"Refactor auth module\"}","Trim-check the objective at the call site before invoking the tool","If building calls from a schema, ensure goalSchema marks objective required for op=create so the model is constrained"],"exampleFix":"// before\nawait tool.execute({ op: \"create\" });\n// after\nawait tool.execute({ op: \"create\", objective: \"Ship the v2 API\" });","handlingStrategy":"validation","validationCode":"if (typeof input.objective !== \"string\" || input.objective.trim().length === 0) {\n  throw new Error(\"objective must be a non-empty string before op=create\");\n}","typeGuard":"function hasObjective(p: { objective?: string }): p is { objective: string } {\n  return typeof p.objective === \"string\" && p.objective.trim().length > 0;\n}","tryCatchPattern":"try {\n  await goalTool.execute({ op: \"create\", objective });\n} catch (err) {\n  if (err instanceof ToolError && err.message.includes(\"objective is required\")) {\n    // prompt user/model for an objective and retry\n  } else throw err;\n}","preventionTips":["Always supply objective when op=create; only omit it for other ops","Trim user/model-provided text before passing","Constrain model tool calls via the goalSchema so objective is required"],"tags":["validation","tool-input","required-parameter"],"backgroundTag":"missing-required-parameter","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}