{"record":{"id":"5ac1bf45e183884c","repo":"TryGhost/Ghost","slug":"failed-to-start-a-members-session","errorCode":null,"errorMessage":"Failed to start a members session","messagePattern":"Failed to start a members session","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/portal/src/utils/api.js","lineNumber":311,"sourceCode":"                return true;\n            });\n        },\n\n        async getIntegrityToken() {\n            const url = endpointFor({type: 'members', resource: 'integrity-token'});\n            const res = await makeRequest({\n                url,\n                method: 'GET'\n            });\n\n            if (res.ok) {\n                return res.text();\n            } else {\n                const humanError = await HumanReadableError.fromApiResponse(res);\n                if (humanError) {\n                    throw humanError;\n                }\n                throw new Error('Failed to start a members session');\n            }\n        },\n\n        /**\n         * @returns {{\n         *     inboxLinks?: {\n         *         desktop: string;\n         *         android: string;\n         *         provider: 'gmail' | 'yahoo' | 'outlook' | 'proton' | 'icloud' | 'hey' | 'aol' | 'mailru';\n         *     };\n         *     otc_ref?: string;\n         * }}\n         */\n        async sendMagicLink({email, emailType, labels, name, oldEmail, newsletters, redirect, integrityToken, phonenumber, customUrlHistory, token, giftToken, autoRedirect = true, includeOTC}) {\n            const url = endpointFor({type: 'members', resource: 'send-magic-link'});\n            const body = {\n                name,\n                email,","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/TryGhost/Ghost/blob/47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe/apps/portal/src/utils/api.js#L293-L329","documentation":"Thrown in api.member.getIntegrityToken() when GET {siteUrl}/members/api/integrity-token/ returns non-ok AND HumanReadableError cannot be parsed from the response. Message 'Failed to start a members session'. The integrity token is the anti-abuse pre-flight for magic-link and checkout flows.","triggerScenarios":"Portal requests an integrity token before sending a magic link or starting checkout; the endpoint responds 4xx/5xx without a JSON errors[] envelope — typically a session/boot failure or an anti-bot challenge rejection.","commonSituations":"Ghost server missing the integrity-token endpoint (older version); reverse proxy returning HTML for the members API; rate-limited by the integrity middleware; CSRF cookie not set; site running behind a cache that returns a stale 5xx.","solutions":["Confirm the Ghost server version exposes /members/api/integrity-token/.","Inspect the raw response in the Network tab — HTML body means upstream proxy/CDN, not Ghost.","Clear cookies for the site and reload so a fresh CSRF/integrity session starts.","Check that the page origin matches siteUrl so cookies are sent correctly."],"exampleFix":"// before\nthrow new Error('Failed to start a members session');\n\n// after\nconst e = new Error(`Failed to start a members session (${res.status})`);\ne.status = res.status;\nthrow e;","handlingStrategy":"retry","validationCode":"// confirm the endpoint exists on the server before relying on it\nasync function serverSupportsIntegrityToken(api) {\n    try {\n        const r = await fetch('/members/api/integrity-token/', {method: 'HEAD'});\n        return r.ok || r.status !== 404;\n    } catch { return true; }\n}","typeGuard":null,"tryCatchPattern":"try {\n    return await api.member.getIntegrityToken();\n} catch (err) {\n    // retry once with a fresh session\n    return retry(() => api.member.getIntegrityToken(), {times: 1});\n}","preventionTips":["Clear site cookies when the integrity session breaks so a fresh one is issued.","Ensure the page origin matches siteUrl so cookies are sent.","Don't cache /members/api/ responses at the edge.","Keep Portal and Ghost server versions aligned on the integrity-token contract."],"tags":["portal","integrity-token","anti-abuse","members-api","session"],"backgroundTag":null,"analyzedSha":"47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe","analyzedAt":"2026-08-13T01:25:26.651Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}