slopus/happy · warning
Claude goal action already in progress
Error message
Claude goal action already in progress
What it means
The goal-action handler enforces one in-flight goal mutation at a time via the pendingClaudeGoalAction guard. If a second goal action arrives while one is still executing, it throws this error instead of queueing or interleaving the operations.
Source
Thrown at packages/happy-cli/src/claude/runClaude.ts:581
model: currentModel,
fallbackModel: currentFallbackModel,
customSystemPrompt: currentCustomSystemPrompt,
appendSystemPrompt: currentAppendSystemPrompt,
allowedTools: currentAllowedTools,
disallowedTools: currentDisallowedTools,
effort: currentEffort,
});
session.rpcHandlerManager.registerHandler('goal-action', async (params: unknown) => {
const actionParams = params && typeof params === 'object' && !Array.isArray(params)
? params as Record<string, unknown>
: null;
const command = actionParams ? parseClaudeGoalActionParams(actionParams) : null;
if (!command) {
throw new Error('Unsupported Claude goal action');
}
if (pendingClaudeGoalAction) {
throw new Error('Claude goal action already in progress');
}
if (!latestClaudeGoalStatus || latestClaudeGoalStatus.status !== 'active') {
throw new Error('No active Claude goal');
}
const capabilities = latestClaudeGoalStatus.capabilities ?? {};
if (command.type === 'clear' && !capabilities.clear) {
throw new Error('Claude clear goal action is not supported');
}
if (command.type === 'set' && !capabilities.edit) {
throw new Error('Claude edit goal action is not supported');
}
if (currentRunMode !== 'remote') {
throw new Error('Claude goal action is not ready: remote mode is not active');
}
if (!currentSession || currentSession.thinking) {
throw new Error('Claude goal action is not ready while Claude is thinking');
}View on GitHub (pinned to b824cd0a46)
Solutions
- Wait for the current goal action to finish before sending another.
- Retry the action after a short delay if the UI gave no feedback.
- Update the app so in-flight actions show a pending state / disable the button.
- Restart the session if pendingClaudeGoalAction appears stuck (a bug worth reporting).
Example fix
// before
rpc('goal-action', { action: 'set', goal: 'x' }); // fired while another in flight
// after
if (!goalActionPending) await rpc('goal-action', { action: 'set', goal: 'x' }); Defensive patterns
Strategy: try-catch
Validate before calling
let goalActionInFlight = false;
async function sendGoalAction(p: unknown) {
if (goalActionInFlight) throw new Error('A goal action is already running');
goalActionInFlight = true;
try { await rpc('goal-action', p); } finally { goalActionInFlight = false; }
} Try / catch
try {
await sendGoalAction({ action: 'clear' });
} catch (err) {
if ((err as Error).message.includes('already in progress')) {
await sleep(1500);
return sendGoalAction({ action: 'clear' });
}
throw err;
} Prevention
- Debounce goal action buttons in the UI.
- Serialize goal actions through a client-side queue.
- Disable the action control while a request is pending.
- Report stuck pendingClaudeGoalAction states as bugs.
When it happens
Trigger: A second 'goal-action' RPC arrives while pendingClaudeGoalAction is still set — e.g. the user taps set/clear twice quickly in the mobile app, or a retry from the app duplicates an in-flight request.
Common situations: Double-tap on the goal UI; slow goal application making the first action appear stuck; app-side retry logic re-sending an unacknowledged action.
Related errors
- No active Claude goal
- Claude goal action is not ready: remote mode is not active
- No active Codex thread
- Backend has been disposed
- Session not started
AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31).
Data as JSON: /api/errors/c372e5dd25e6526c.
Report an issue: GitHub.