coleam00/Archon · error
Run ${run.id}'s gate only accepts 'approve' or 'reject' — '$
Error message
Run ${run.id}'s gate only accepts 'approve' or 'reject' — '${decision}' is not one of its declared decisions. Declare `approval.decisions:` on the gate node to author a broader vocabulary. What it means
assertRespondable throws this when the gate is an approval gate but has NOT authored a custom decisions list (decisionsAuthored !== true), and the caller supplied a decision other than 'approve'/'reject'. Undecorated approval gates only synthesize the binary approve/reject pair, so any other vocabulary is refused.
Source
Thrown at packages/core/src/operations/workflow-operations.ts:902
* existing `approveWorkflow`/`rejectWorkflow` machinery by `respondToWorkflow`
* — this function is not consulted for those two ids). Any OTHER decision is
* legal only for a plain gate node (`approval`/`undefined` suspend type) whose
* author explicitly declared `approval.decisions:` (`decisionsAuthored`) —
* `writeback`/`interactive_loop`/`child_workflow` pauses have no author-
* declared vocabulary and accept only approve/reject; a legacy gate (no
* `decisions:` authored) also only ever has the synthesized approve/reject
* pair (#2707 step 2).
*/
export function assertRespondable(run: WorkflowRun, decision: string): ApprovalContext {
const approval = assertApprovable(run);
if (approval.type !== 'approval' && approval.type !== undefined) {
throw new Error(
`Run ${run.id}'s gate ('${approval.type}') only accepts 'approve' or 'reject' — ` +
`'${decision}' is not a valid response here.`
);
}
if (approval.decisionsAuthored !== true) {
throw new Error(
`Run ${run.id}'s gate only accepts 'approve' or 'reject' — '${decision}' is not one of its ` +
'declared decisions. Declare `approval.decisions:` on the gate node to author a broader vocabulary.'
);
}
const declaredIds = (approval.decisions ?? []).map(d => d.id);
if (!declaredIds.includes(decision)) {
throw new Error(
`Run ${run.id}'s gate does not declare decision '${decision}'. Declared decisions: ` +
`${declaredIds.join(', ')}.`
);
}
return approval;
}
/**
* Resolve a paused gate with an author-declared decision beyond approve/reject
* (#2707 step 2 — the general `workflow respond <id> <decision> [text]` verb).
* `approve`/`reject` are NOT handled here — `respondToWorkflow` delegates thoseView on GitHub (pinned to 0773b97458)
Solutions
- Add `approval.decisions:` entries on the gate node to declare the custom decision ids you want to accept.
- Alternatively respond with the plain 'approve' or 'reject' the uncustomized gate supports.
- Fetch the run's approval context first and only send decisions it declares.
Example fix
// before (workflow YAML)
- id: review
type: approval
// after
- id: review
type: approval
approval:
decisions:
- id: request_changes
- id: approve Defensive patterns
Strategy: validation
Validate before calling
const allowed = gate.decisionsAuthored ? gate.decisions.map(d => d.id) : ['approve', 'reject'];
if (!allowed.includes(decision)) {
throw new Error(`Decision '${decision}' not allowed; allowed: ${allowed.join(', ')}`);
} Type guard
function isBinaryDecision(decision) {
return decision === 'approve' || decision === 'reject';
} Try / catch
try {
await respondToWorkflow(runId, decision);
} catch (e) {
if (e.message.includes('not one of its declared decisions')) {
await respondToWorkflow(runId, isBinaryDecision(decision) ? decision : 'reject');
} else throw e;
} Prevention
- Declare approval.decisions on any gate intended for non-binary responses.
- Derive the UI's decision buttons from the run's declared decisions, not a hardcoded list.
- Keep workflow YAML and calling scripts reviewed together when changing gate vocabulary.
When it happens
Trigger: Responding to a run with decision strings like 'request_changes' or 'approve_with_comments' when the gate node lacks an `approval.decisions:` declaration; e.g. `respondToWorkflow(runId, 'request_changes')` on a gate authored without decisions.
Common situations: A developer adds a richer decision word to a bot/CLI call assuming gates accept free-form decisions; a workflow author forgot to add `approval.decisions:` before wiring custom responses; copy-pasted response code from a workflow that did declare decisions.
Related errors
- Run ${run.id}'s gate does not declare decision '${decision}'
- Run ${run.id}'s gate ('${approval.type}') only accepts 'appr
- Invalid --status '${opts.status}'. Valid: ${workflowRunStatu
- Cannot signal a non-event workflow wait
- Node '${consumerId}' binding '${name}': an object value must
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/c1e90ed7b31e459f.
Report an issue: GitHub.