Yeachan-Heo/oh-my-codex · error · UltragoalError
Invalid --source: ${raw}. Expected one of ${Array.from(STEER
Error message
Invalid --source: ${raw}. Expected one of ${Array.from(STEERING_SOURCES).join(', ')}. What it means
--source on `omx ultragoal steer` labels where the steering proposal came from and must be one of the ULTRAGOAL_STEERING_SOURCES enum (default 'cli' when omitted). parseSteeringSource throws for any unrecognized string; the accepted list is embedded in the message.
Source
Thrown at src/cli/ultragoal.ts:230
cwd: scope.cwd,
sessionId: scope.sessionId,
});
}
const STEERING_KINDS = new Set<UltragoalSteeringMutationKind>(ULTRAGOAL_STEERING_MUTATION_KINDS);
const STEERING_SOURCES = new Set<UltragoalSteeringSource>(ULTRAGOAL_STEERING_SOURCES);
type CliSteerResult = Awaited<ReturnType<typeof steerUltragoal>>;
function parseSteeringKind(raw: string | undefined): UltragoalSteeringMutationKind {
if (!raw) throw new UltragoalError('Missing --kind for structured ultragoal steer.');
if (!STEERING_KINDS.has(raw as UltragoalSteeringMutationKind)) throw new UltragoalError(`Invalid --kind: ${raw}. Expected one of ${Array.from(STEERING_KINDS).join(', ')}.`);
return raw as UltragoalSteeringMutationKind;
}
function parseSteeringSource(raw: string | undefined, fallback: UltragoalSteeringSource = 'cli'): UltragoalSteeringSource {
if (!raw) return fallback;
if (!STEERING_SOURCES.has(raw as UltragoalSteeringSource)) throw new UltragoalError(`Invalid --source: ${raw}. Expected one of ${Array.from(STEERING_SOURCES).join(', ')}.`);
return raw as UltragoalSteeringSource;
}
function assertPlainObject(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new UltragoalError(`${label} must be a JSON object.`);
return value as Record<string, unknown>;
}
function normalizeTargetGoalId(raw: Record<string, unknown>): string | undefined {
if (typeof raw.targetGoalId === 'string' && raw.targetGoalId.trim()) return raw.targetGoalId.trim();
if (Array.isArray(raw.targetGoalIds)) return raw.targetGoalIds.find((id): id is string => typeof id === 'string' && id.trim().length > 0)?.trim();
return undefined;
}
function normalizeSteeringProposal(raw: Record<string, unknown>, _fallbackDirectiveText?: string): UltragoalSteeringProposal {
const kind = parseSteeringKind(typeof raw.kind === 'string' ? raw.kind : undefined);
const source = parseSteeringSource(typeof raw.source === 'string' ? raw.source : undefined);
const after = raw.after && typeof raw.after === 'object' && !Array.isArray(raw.after)View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Use one of the exact values printed in the error message (e.g. 'cli')
- Omit --source to get the default 'cli'
- Update to the latest version if you need a new source label that docs advertise
Example fix
# before omx ultragoal steer --kind update_goal --source api ... # Error: Invalid --source: api. Expected one of cli, agent. # after omx ultragoal steer --kind update_goal --source agent ...
Defensive patterns
Strategy: type-guard
Validate before calling
const SOURCES = new Set(ULTRAGOAL_STEERING_SOURCES as readonly string[]);
if (source && !SOURCES.has(source)) { console.error(`--source must be one of: ${[...SOURCES].join(', ')}`); process.exit(2); } Type guard
function isSteeringSource(v: string, valid: ReadonlySet<string>): v is (typeof ULTRAGOAL_STEERING_SOURCES)[number] {
return valid.has(v);
} Prevention
- Omit --source unless you need a non-default provenance label
- Lowercase all source values; the enum is case-sensitive
When it happens
Trigger: Passing `--source api`, `--source codex`, or a typo'd value not in ULTRAGOAL_STEERING_SOURCES; correct values are typically 'cli', 'agent', etc. per the exported enum.
Common situations: Teams piping steering from automation assuming an arbitrary source label works; copy-paste from older docs where the enum was smaller; case sensitivity ('CLI' vs 'cli').
Related errors
- Invalid --codex-goal-mode; expected aggregate or per-story.
- Invalid --kind: ${raw}. Expected one of ${Array.from(STEERIN
- Unsupported mission mark status: ${value}
- --keep-policy must be one of: score_improvement, pass_only
- Unknown capabilities subcommand: ${parsed.subcommand}
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/ca5e8cb15e185283.
Report an issue: GitHub.