{"record":{"id":"d1bf52a06e1660ef","repo":"Significant-Gravitas/AutoGPT","slug":"pkce-verifier-not-found-in-session","errorCode":null,"errorMessage":"PKCE verifier not found in session","messagePattern":"PKCE verifier not found in session","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"autogpt_platform/backend/backend/cli/oauth_tool.py","lineNumber":683,"sourceCode":"                providers: providersBase64,\n                redirect_uri: config.redirectUri,\n                state: currentState\n            }});\n\n            const wizardUrl = `${{config.platformUrl}}/auth/integrations/setup-wizard?${{params}}`;\n            log(`Redirecting to: ${{wizardUrl}}`);\n\n            sessionStorage.setItem('wizard_state', currentState);\n\n            window.location.href = wizardUrl;\n        }}\n\n        async function exchangeCodeForTokens(code) {{\n            log('Exchanging authorization code for tokens...');\n\n            const verifier = sessionStorage.getItem('oauth_pkce_verifier');\n            if (!verifier) {{\n                throw new Error('PKCE verifier not found in session');\n            }}\n\n            // Use local proxy to avoid CORS issues\n            // The proxy forwards the request to the backend\n            const response = await fetch('/proxy/token', {{\n                method: 'POST',\n                headers: {{ 'Content-Type': 'application/json' }},\n                body: JSON.stringify({{\n                    grant_type: 'authorization_code',\n                    code: code,\n                    redirect_uri: config.redirectUri,\n                    client_id: config.clientId,\n                    client_secret: config.clientSecret,\n                    code_verifier: verifier\n                }})\n            }});\n\n            if (!response.ok) {{","sourceCodeStart":665,"sourceCodeEnd":701,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/cli/oauth_tool.py#L665-L701","documentation":"Raised by approve_transfer when the caller's active org is the source org and sourceApprovedByUserId is already set. Each side of a transfer may approve exactly once; a second approval attempt from the source side is rejected. Guards against double-approval by different users of the same org.","triggerScenarios":"User A in the source org approves (sets sourceApprovedByUserId), then User B (or User A again) in the same org calls approve on the same transfer. Any POST approve from the source org after sourceApprovedByUserId is non-null.","commonSituations":"Two admins in the same org both clicking approve; a retry of a timed-out approve request that actually succeeded; frontend not reflecting that the current org already approved.","solutions":["Check the transfer's sourceApprovedByUserId / targetApprovedByUserId fields in the UI and hide the approve action for a side that has already approved.","Catch this ValueError in the client and treat it as success-equivalent (the org's approval is recorded) after re-fetching the transfer.","Add idempotency: if sourceApprovedByUserId == user_id, return the current row instead of raising."],"exampleFix":"# before\nawait approve_transfer(tid, user_id, org_id)\n\n# after\ntr = await get_transfer(tid)\nif tr.source_approved_by_user_id is None or tr.target_approved_by_user_id is None:\n    await approve_transfer(tid, user_id, org_id)","handlingStrategy":"validation","validationCode":"tr = await get_transfer(transfer_id)\nif org_id == tr.source_org_id and tr.source_approved_by_user_id is not None:\n    return  # source already approved; nothing to do","typeGuard":"def source_already_approved(tr: TransferResponse, org_id: str) -> bool:\n    return org_id == tr.source_org_id and tr.source_approved_by_user_id is not None","tryCatchPattern":"try:\n    await approve_transfer(tid, user_id, org_id)\nexcept ValueError as e:\n    if \"already approved\" in str(e):\n        pass  # idempotent: approval recorded\n    else:\n        raise","preventionTips":["Hide the approve control for a side whose *ApprovedByUserId is set","Make approve idempotent client-side by checking the approval fields first","Coordinate among org admins to avoid duplicate approvals"],"tags":["transfers","idempotency","approval"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}