{"record":{"id":"c372e5dd25e6526c","repo":"slopus/happy","slug":"claude-goal-action-already-in-progress","errorCode":null,"errorMessage":"Claude goal action already in progress","messagePattern":"Claude goal action already in progress","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/happy-cli/src/claude/runClaude.ts","lineNumber":581,"sourceCode":"        model: currentModel,\n        fallbackModel: currentFallbackModel,\n        customSystemPrompt: currentCustomSystemPrompt,\n        appendSystemPrompt: currentAppendSystemPrompt,\n        allowedTools: currentAllowedTools,\n        disallowedTools: currentDisallowedTools,\n        effort: currentEffort,\n    });\n\n    session.rpcHandlerManager.registerHandler('goal-action', async (params: unknown) => {\n        const actionParams = params && typeof params === 'object' && !Array.isArray(params)\n            ? params as Record<string, unknown>\n            : null;\n        const command = actionParams ? parseClaudeGoalActionParams(actionParams) : null;\n        if (!command) {\n            throw new Error('Unsupported Claude goal action');\n        }\n        if (pendingClaudeGoalAction) {\n            throw new Error('Claude goal action already in progress');\n        }\n        if (!latestClaudeGoalStatus || latestClaudeGoalStatus.status !== 'active') {\n            throw new Error('No active Claude goal');\n        }\n\n        const capabilities = latestClaudeGoalStatus.capabilities ?? {};\n        if (command.type === 'clear' && !capabilities.clear) {\n            throw new Error('Claude clear goal action is not supported');\n        }\n        if (command.type === 'set' && !capabilities.edit) {\n            throw new Error('Claude edit goal action is not supported');\n        }\n        if (currentRunMode !== 'remote') {\n            throw new Error('Claude goal action is not ready: remote mode is not active');\n        }\n        if (!currentSession || currentSession.thinking) {\n            throw new Error('Claude goal action is not ready while Claude is thinking');\n        }","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/slopus/happy/blob/b824cd0a4681d41af631a8e422a813873e4455b0/packages/happy-cli/src/claude/runClaude.ts#L563-L599","documentation":"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.","triggerScenarios":"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.","commonSituations":"Double-tap on the goal UI; slow goal application making the first action appear stuck; app-side retry logic re-sending an unacknowledged action.","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)."],"exampleFix":"// before\nrpc('goal-action', { action: 'set', goal: 'x' }); // fired while another in flight\n// after\nif (!goalActionPending) await rpc('goal-action', { action: 'set', goal: 'x' });","handlingStrategy":"try-catch","validationCode":"let goalActionInFlight = false;\nasync function sendGoalAction(p: unknown) {\n  if (goalActionInFlight) throw new Error('A goal action is already running');\n  goalActionInFlight = true;\n  try { await rpc('goal-action', p); } finally { goalActionInFlight = false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await sendGoalAction({ action: 'clear' });\n} catch (err) {\n  if ((err as Error).message.includes('already in progress')) {\n    await sleep(1500);\n    return sendGoalAction({ action: 'clear' });\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["rpc","concurrency","state"],"backgroundTag":"action-already-in-progress","analyzedSha":"b824cd0a4681d41af631a8e422a813873e4455b0","analyzedAt":"2026-08-31T23:12:36.205Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}