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

  1. Confirm the Ghost server version exposes /members/api/integrity-token/.
  2. Inspect the raw response in the Network tab — HTML body means upstream proxy/CDN, not Ghost.
  3. Clear cookies for the site and reload so a fresh CSRF/integrity session starts.
  4. 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

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


AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13). Data as JSON: /api/errors/5ac1bf45e183884c. Report an issue: GitHub.