slopus/happy · warning

No active Claude goal

Error message

No active Claude goal

What it means

Goal actions require an active goal state tracked in latestClaudeGoalStatus. If no status has been received yet, or its status is not 'active', the handler rejects set/clear actions with this error because there is no goal machinery in a state that can accept commands.

Source

Thrown at packages/happy-cli/src/claude/runClaude.ts:584

        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');
        }
        if (messageQueue.size() > 0) {
            throw new Error('Claude message queue is busy');
        }

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Refresh the goal state in the mobile app before acting.
  2. Set a goal first (status must be 'active') before attempting further actions.
  3. Re-sync the session / reopen it so latestClaudeGoalStatus is repopulated.
  4. Update app+CLI so stale UI is invalidated when the goal status changes.

Example fix

// before
await rpc('goal-action', { action: 'clear' }); // no active goal
// after
if (goalStatus?.status === 'active') await rpc('goal-action', { action: 'clear' });
Defensive patterns

Strategy: validation

Validate before calling

if (goalStatus?.status !== 'active') {
  console.warn('No active goal — skipping action');
  return;
}

Type guard

function hasActiveGoal(s: { status: string } | null | undefined): s is { status: 'active' } & Record<string, unknown> {
  return s !== null && s !== undefined && s.status === 'active';
}

Try / catch

try {
  await rpc('goal-action', { action: 'clear' });
} catch (err) {
  if ((err as Error).message === 'No active Claude goal') {
    logger.warn('Goal action ignored: no active goal — refresh goal state first');
  } else throw err;
}

Prevention

When it happens

Trigger: A 'goal-action' RPC arrives before the CLI has received any goal status from Claude, or after the goal transitioned out of 'active' (e.g. already cleared or finished).

Common situations: Sending a clear action when no goal was ever set; acting on a stale UI after the goal completed; session restart wiping goal state while the mobile UI still shows an active goal.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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