{"record":{"id":"8e803ab33eb805b4","repo":"aaif-goose/goose","slug":"cannot-update-message-because-the-active-prompt-co","errorCode":null,"errorMessage":"Cannot update message because the active prompt could not be cancelled","messagePattern":"Cannot update message because the active prompt could not be cancelled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ui/desktop/src/acp/chatSessionController.ts","lineNumber":301,"sourceCode":"      pendingToolPermissionPromptAttemptId\n    );\n    if (!cancellation) {\n      throw new Error('Cannot update message while prompt is active');\n    }\n\n    const promptCancellationSettled = acpChatSessionActions.waitForPromptCancellation(\n      sessionId,\n      pendingToolPermissionPromptAttemptId\n    );\n\n    try {\n      await acpCancelPrompt(sessionId);\n    } catch {\n      acpChatSessionActions.restorePromptCancellation(\n        sessionId,\n        pendingToolPermissionPromptAttemptId\n      );\n      throw new Error('Cannot update message because the active prompt could not be cancelled');\n    }\n\n    cancelAcpPermissionRequestsForSession(sessionId);\n    cancelAcpElicitationRequestsForSession(sessionId);\n    await promptCancellationSettled;\n  }\n\n  acpChatSessionActions.setChatState(sessionId, ChatState.Thinking);\n\n  try {\n    await acpTruncateSessionConversation(sessionId, message.created);\n\n    const truncatedMessages = currentMessages.filter((m) => m.created < message.created);\n    const updatedUserMessage = createUserMessage(newContent, retainedImages);\n\n    const messagesForUI = [...truncatedMessages, updatedUserMessage];\n    acpChatSessionActions.setMessages(sessionId, messagesForUI);\n","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/ui/desktop/src/acp/chatSessionController.ts#L283-L319","documentation":"Thrown in the same edit path after startPromptCancellation succeeded: the actual ACP call acpCancelPrompt(sessionId) rejected, so the active prompt could not be cancelled on the agent. The catch block first restores the prompt-cancellation state (restorePromptCancellation) to keep the store consistent, then throws this error. Root causes live in the ACP session: connection dropped, session id no longer valid on the backend, or the agent rejecting cancellation.","triggerScenarios":"Editing a message while the permission prompt is active, but the websocket to goose has disconnected or the session was closed/restarted server-side; acpCancelPrompt timing out; session id from a previous backend run.","commonSituations":"Backend restart under the desktop app; network blip dropping the ACP socket; user edits during a long-running tool permission while the agent process is being updated.","solutions":["Check the ACP connection state (getAcpClient connectivity) — if the socket is dead, reconnect and retry the edit.","Verify the session still exists on the backend (session list) before retrying; recreate/recover the session if it was lost.","Look at the underlying error from acpCancelPrompt in devtools — this thrown Error deliberately hides it; log the original cause.","Retry the edit after reconnection: state was restored, so the edit can be re-submitted safely."],"exampleFix":"// before\ntry {\n  await acpCancelPrompt(sessionId);\n} catch {\n  acpChatSessionActions.restorePromptCancellation(sessionId, pendingToolPermissionPromptAttemptId);\n  throw new Error('Cannot update message because the active prompt could not be cancelled');\n}\n\n// after (keep the cause chained)\ntry {\n  await acpCancelPrompt(sessionId);\n} catch (cause) {\n  acpChatSessionActions.restorePromptCancellation(sessionId, pendingToolPermissionPromptAttemptId);\n  throw new Error('Cannot update message because the active prompt could not be cancelled', { cause });\n}","handlingStrategy":"try-catch","validationCode":"// Confirm the ACP connection is alive before attempting prompt cancellation\nconst healthy = await isAcpConnectionHealthy(sessionId); // e.g. ping/status via client\nif (!healthy) {\n  await reconnectAcp();\n}","typeGuard":null,"tryCatchPattern":"try {\n  await submitEditedMessage(sessionId, messageId, newContent, retainedImages, options);\n} catch (error) {\n  if (/could not be cancelled/.test(String(error))) {\n    // State was restored by the controller; safe to reconnect and retry the edit once\n    await reconnectAcp();\n    return submitEditedMessage(sessionId, messageId, newContent, retainedImages, options);\n  }\n  throw error;\n}","preventionTips":["Trigger reconnect logic on any cancellation failure rather than leaving the UI stuck in Thinking.","Chain the underlying cause when rethrowing so backend errors are diagnosable.","Health-check the ACP socket before edits that require cancelling an active prompt."],"tags":["acp","cancellation","connection","chat"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}