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

  1. Wait for the current goal action to finish before sending another.
  2. Retry the action after a short delay if the UI gave no feedback.
  3. Update the app so in-flight actions show a pending state / disable the button.
  4. 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

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


AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31). Data as JSON: /api/errors/c372e5dd25e6526c. Report an issue: GitHub.