can1357/oh-my-pi · error · Error
objective is required when op=replace
Error message
objective is required when op=replace
What it means
replaceGoal requires a non-empty objective string, mirroring createGoal. The runtime trims the input and throws when nothing remains, since replacing a goal with no objective would leave the tracker without a target.
Source
Thrown at packages/coding-agent/src/goals/runtime.ts:403
const objective = input.objective.trim();
if (!objective) throw new Error("objective is required when op=create");
validateTokenBudget(input.tokenBudget);
return await this.#withAccounting(async () => {
const existing = this.#host.getState();
if (existing?.goal && existing.goal.status !== "dropped" && existing.goal.status !== "complete") {
throw new Error("cannot create a new goal because this session already has a goal");
}
const state = this.#createGoalState(objective, input.tokenBudget);
this.#budgetReportedFor = undefined;
this.#markActiveAccounting(state.goal);
await this.#commitState(state, { persist: "goal" });
return state;
});
}
async replaceGoal(input: { objective: string; tokenBudget?: number }): Promise<GoalModeState> {
const objective = input.objective.trim();
if (!objective) throw new Error("objective is required when op=replace");
validateTokenBudget(input.tokenBudget);
return await this.#withAccounting(async () => {
const existing = this.#host.getState();
if (!existing?.enabled || !isAccountingStatus(existing.goal)) {
throw new Error("cannot replace goal because no goal is active");
}
await this.#flushUsageLocked("suppressed");
const state = this.#createGoalState(objective, input.tokenBudget);
this.#budgetReportedFor = undefined;
this.#markActiveAccounting(state.goal);
await this.#commitState(state, { persist: "goal" });
return state;
});
}
async resumeGoal(): Promise<GoalModeState> {
return await this.#withAccounting(async () => {
const state = this.#getStateClone();View on GitHub (pinned to 9690622007)
Solutions
- Supply a non-empty objective when calling replaceGoal
- Validate/trim the objective in the caller before invoking the runtime
- Reject blank objective at the input schema level
Example fix
// before
await runtime.replaceGoal({ objective: draft });
// after
const objective = draft.trim();
if (!objective) throw new Error('New goal objective must not be empty');
await runtime.replaceGoal({ objective }); Defensive patterns
Strategy: validation
Validate before calling
if (typeof objective !== 'string' || objective.trim().length === 0) {
throw new Error('objective must be a non-empty string');
} Type guard
function hasObjective(input: { objective: string }): boolean {
return typeof input.objective === 'string' && input.objective.trim().length > 0;
} Try / catch
try {
await runtime.replaceGoal({ objective });
} catch (err) {
if (err instanceof Error && err.message === 'objective is required when op=replace') {
return { ok: false, reason: 'empty-objective' };
}
throw err;
} Prevention
- Validate edit-form input before submitting (non-empty after trim)
- Apply the same objective validation helper used for createGoal
- Require the objective field in your tool argument schema
When it happens
Trigger: Calling replaceGoal with objective '' or whitespace-only; dropping the objective field when building tool arguments; upstream code joining an empty array into ''.
Common situations: Interactive goal-edit flows submitted with a blank field; LLM tool calls missing the objective argument; templates with unfilled placeholders.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- goal token_budget must be a positive integer when provided
- objective is required when op=create
- Expected --${name} to be a positive integer, got ${value}
- Cache flags require --cache
- --alias requires --profile <name> or OMP_PROFILE
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/96664344f5ffd0ef.
Report an issue: GitHub.