can1357/oh-my-pi · error · ToolError

token_budget must be a positive integer when provided

Error message

token_budget must be a positive integer when provided

What it means

The optional `token_budget` parameter of goal create must be a positive integer when provided. validateCreateParams rejects undefined-only absence but any provided value that is not an integer (float, 0, negative, NaN) throws this ToolError.

Source

Thrown at packages/coding-agent/src/goals/tools/goal-tool.ts:53

	const resolvedGoal = goal ?? null;
	return {
		goal: resolvedGoal,
		remainingTokens: remainingTokens(resolvedGoal),
		completionBudgetReport:
			options?.includeCompletionReport && resolvedGoal?.status === "complete"
				? completionBudgetReport(resolvedGoal)
				: null,
	};
}

function validateCreateParams(params: GoalToolInput): { objective: string; tokenBudget?: number } {
	const objective = params.objective?.trim();
	if (!objective) {
		throw new ToolError("objective is required when op=create");
	}
	const tokenBudget = params.token_budget;
	if (tokenBudget !== undefined && (!Number.isInteger(tokenBudget) || tokenBudget <= 0)) {
		throw new ToolError("token_budget must be a positive integer when provided");
	}
	return { objective, tokenBudget };
}

export class GoalTool implements AgentTool<typeof goalSchema, GoalToolDetails> {
	readonly name = "goal";
	readonly label = "Goal";
	readonly description = prompt.render(goalDescription);
	readonly parameters = goalSchema;
	readonly strict = true;
	readonly intent = "omit" as const;
	readonly #session: ToolSession;

	constructor(session: ToolSession) {
		this.#session = session;
	}

	async execute(

View on GitHub (pinned to 9690622007)

Solutions

  1. Omit `token_budget` entirely if you don't want a budget (only validate when defined)
  2. Round/parse the value to a positive integer before calling: Number.isInteger(v) && v > 0
  3. Coerce numeric strings with Number() and validate before passing

Example fix

// before
await tool.execute({ op: "create", objective: "x", token_budget: 0 });
// after
await tool.execute({ op: "create", objective: "x", token_budget: 4096 });
Defensive patterns

Strategy: validation

Validate before calling

if (input.token_budget !== undefined && (!Number.isInteger(input.token_budget) || input.token_budget <= 0)) {
  throw new Error("token_budget must be a positive integer");
}

Type guard

function isValidTokenBudget(v: unknown): v is number {
  return typeof v === "number" && Number.isInteger(v) && v > 0;
}

Try / catch

try {
  await goalTool.execute({ op: "create", objective, token_budget });
} catch (err) {
  if (err instanceof ToolError && err.message.includes("token_budget")) {
    // drop or correct the budget and retry
  } else throw err;
}

Prevention

When it happens

Trigger: Calling goal op=create with token_budget=0, a negative number, a float like 1024.5, or a non-numeric value; passing token_budget: null or a numeric string.

Common situations: An LLM hallucinates a budget of 0 or a decimal; callers pass user-typed CLI/config values that were never parsed to an integer; copying examples with placeholder values.

Understand the failure class

Background: "must be positive", "Invalid value": how libraries reject invalid parameter values (ValueError, ArgumentError, INVALID_PARAMETER_VALUE) — this error's family across 28 libraries.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/77e80888225631a1. Report an issue: GitHub.