TryGhost/Ghost · error · Error

result.error.message

Error message

result.error.message

What it means

Thrown inside editBilling() after the backend returned a valid update session but Stripe.js redirectToCheckout() failed. Same Stripe-redirect failure class as errors 81/83, scoped to the card-update (billing edit) flow. The session was created; the browser-side handoff to Stripe's hosted checkout broke.

Source

Thrown at apps/portal/src/utils/api.js:768

                body: JSON.stringify({
                    identity: identity,
                    subscription_id: subscriptionId,
                    successUrl,
                    cancelUrl
                })
            }).then(function (res) {
                if (!res.ok) {
                    throw new Error('Unable to create stripe checkout session');
                }
                return res.json();
            }).then(function (result) {
                const stripe = window.Stripe(result.publicKey);
                return stripe.redirectToCheckout({
                    sessionId: result.sessionId
                });
            }).then(function (result) {
                if (result.error) {
                    throw new Error(result.error.message);
                }
            }).catch(function (err) {
                throw err;
            });
        },

        async manageBilling({returnUrl, subscriptionId} = {}) {
            const identity = await api.member.identity();
            const url = endpointFor({type: 'members', resource: 'create-stripe-billing-portal-session'});
            if (!returnUrl) {
                const returnUrlObj = new URL(siteUrl);
                returnUrlObj.searchParams.set('stripe', 'billing-portal-closed');
                returnUrl = returnUrlObj.href;
            }

            return makeRequest({
                url,
                method: 'POST',

View on GitHub (pinned to 47d8b0e2ad)

Solutions

  1. Close and reopen the edit-billing flow to mint a fresh session.
  2. Verify Stripe publishable key parity in Ghost Admin settings.
  3. Check browser console for the Stripe.js error code/type.
  4. Consult status.stripe.com for a Checkout incident.
Defensive patterns

Strategy: try-catch

Validate before calling

function stripeReady() {
    return typeof window.Stripe === 'function';
}

Type guard

function isStripeRedirectError(result) {
    return result && typeof result.error === 'object' && typeof result.error.message === 'string';
}

Try / catch

try {
    await api.member.editBilling({subscriptionId});
} catch (err) {
    if (/session|stripe/i.test(err.message)) {
        // re-enter edit billing to mint a fresh session
    }
    showToast(err.message);
}

Prevention

When it happens

Trigger: stripe.redirectToCheckout({sessionId}) resolves with {error} for the billing-update session — expired sessionId, publishable key mismatch with the session's account, Stripe.js blocked, or the session already consumed.

Common situations: Member opened the edit-billing flow, left it idle past the session expiry, then clicked through; Stripe keys changed in Ghost Admin between session creation and redirect; Stripe.js blocked by CSP/ad-blocker; Stripe partial outage on Checkout.

Related errors


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