{"record":{"id":"909b88475a98edac","repo":"deepseek-ai/deepseek-harness","slug":"approval-response-rejected-receipt-reason","errorCode":null,"errorMessage":"approval response rejected: ${receipt.reason}","messagePattern":"approval response rejected: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/client/ui-conversation/src/client/contract/slots.ts","lineNumber":720,"sourceCode":"\n  /** The paired tool call's id when the ask names one (command-line lookup key), forwarded from the carrier payload. */\n  get callId(): string | undefined {\n    return this.wait.payload.callId\n  }\n\n  /**\n   * Deliver the user's decision; a rejected carrier receipt throws. Panel\n   * removal stays frame-driven: the broadcast `approval/resolved` settles the\n   * wait and drops it from the pending list.\n   * @param outcome - the only two client-answerable outcomes.\n   */\n  async answer(outcome: 'allowed-once' | 'rejected'): Promise<void> {\n    const receipt = await this.wait.respond({\n      ok: true,\n      value: { sessionId: this.wait.sessionId, approvalId: this.wait.payload.approvalId, outcome },\n    })\n    if (!receipt.accepted) {\n      throw new Error(`approval response rejected: ${receipt.reason}`)\n    }\n  }\n}\n\n/**\n * Full approval-composer props: the framework runtime share (chain currency +\n * session/global standard kit) plus the chain `matched` share — the entry's\n * selector result, already narrowed to the approval carrier — plus the\n * standard locale seat. No injected share: the carrier plus the domain face\n * above carry the whole behavior surface; the paired command line derives\n * from useSession in-component.\n */\nexport type ApprovalComposerProps =\n  PropsRuntime<'conversation.composer'> & { matched: ApprovalWait } & PropsLocale<'conversation'>\n\n/** In-memory reader position resilient to transcript width reflow. */\nexport interface ChatScrollPosition {\n  /** Stable rendered node/call identity nearest the visible reading edge. */","sourceCodeStart":702,"sourceCodeEnd":738,"githubUrl":"https://github.com/deepseek-ai/deepseek-harness/blob/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e/packages/client/ui-conversation/src/client/contract/slots.ts#L702-L738","documentation":"PendingApproval.answer() delivers the user's allowed-once/rejected decision through the carrier wait's respond(). The host reconciles approval responses against its pending set; if the response arrives too late or duplicates another answer, the receipt comes back accepted:false with a reason, which answer() rethrows as 'approval response rejected: <reason>'. Panel removal stays frame-driven via the broadcast approval/resolved event.","triggerScenarios":"Answering an approval that was already settled elsewhere: double-clicking Allow/Reject, a second panel answering the same approvalId, the host or another client (CLI plus web) answering first, or the approval/resolved broadcast landing while the user's click is still in flight.","commonSituations":"Race between the resolved-event broadcast removing the panel and the user's click; retry logic that re-fires answer() after a timeout; multi-surface setups where either surface can decide.","solutions":["Treat as benign when the approval already resolved — check the pending list or the approval/resolved event before reporting an error","Latch the Allow/Reject buttons one-shot so a second click cannot fire answer() twice","If the reason says the wait never existed, resync session state to rebuild the pending approvals view"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await approval.answer(outcome)\n} catch (error) {\n  if (approvalAlreadyResolved(approval.key)) return // benign double-answer race\n  throw error\n}","preventionTips":["Latch Allow/Reject buttons one-shot so a second click cannot fire answer() twice","Drop the panel when the approval/resolved broadcast lands, before processing further clicks","Never auto-retry answer() after a rejected receipt — resync pending state instead"],"tags":["approvals","race-condition","ui","idempotency"],"backgroundTag":"approval-already-answered","analyzedSha":"b150a551b8d465e31e418e1b2eaf5e79bbb7d28e","analyzedAt":"2026-08-24T18:12:29.105Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}