TryGhost/Ghost · error · Error
Failed to start a members session
Error message
Failed to start a members session
What it means
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.
Source
Thrown at apps/portal/src/utils/api.js:311
return true;
});
},
async getIntegrityToken() {
const url = endpointFor({type: 'members', resource: 'integrity-token'});
const res = await makeRequest({
url,
method: 'GET'
});
if (res.ok) {
return res.text();
} else {
const humanError = await HumanReadableError.fromApiResponse(res);
if (humanError) {
throw humanError;
}
throw new Error('Failed to start a members session');
}
},
/**
* @returns {{
* inboxLinks?: {
* desktop: string;
* android: string;
* provider: 'gmail' | 'yahoo' | 'outlook' | 'proton' | 'icloud' | 'hey' | 'aol' | 'mailru';
* };
* otc_ref?: string;
* }}
*/
async sendMagicLink({email, emailType, labels, name, oldEmail, newsletters, redirect, integrityToken, phonenumber, customUrlHistory, token, giftToken, autoRedirect = true, includeOTC}) {
const url = endpointFor({type: 'members', resource: 'send-magic-link'});
const body = {
name,
email,View on GitHub (pinned to 47d8b0e2ad)
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.
Example fix
// before
throw new Error('Failed to start a members session');
// after
const e = new Error(`Failed to start a members session (${res.status})`);
e.status = res.status;
throw e; Defensive patterns
Strategy: retry
Validate before calling
// confirm the endpoint exists on the server before relying on it
async function serverSupportsIntegrityToken(api) {
try {
const r = await fetch('/members/api/integrity-token/', {method: 'HEAD'});
return r.ok || r.status !== 404;
} catch { return true; }
} Try / catch
try {
return await api.member.getIntegrityToken();
} catch (err) {
// retry once with a fresh session
return retry(() => api.member.getIntegrityToken(), {times: 1});
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to update newsletter
- Failed to signout
- Failed to update member
- Failed to fetch site data
- fallbackMessage
AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13).
Data as JSON: /api/errors/5ac1bf45e183884c.
Report an issue: GitHub.