TryGhost/Ghost · error · Error

Failed to continue gift subscription, please try again.

Error message

Failed to continue gift subscription, please try again.

What it means

Thrown by continueGiftCheckout() when the POST to the members 'create-stripe-checkout-session' endpoint (with continueFromGift:true) returns non-2xx. The client prefers the backend's errors[0].message and only falls back to this generic string when no structured error body is present. continueGiftCheckout upgrades a redeemed gift subscription into a recurring paid plan.

Source

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

                metadata: {
                    checkoutType: 'upgrade',
                    requestSrc: 'portal',
                    urlHistory: getUrlHistory()
                }
            };

            return makeRequest({
                url,
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(body)
            }).then(async function (res) {
                if (!res.ok) {
                    const errData = await res.json();
                    const errMssg = errData?.errors?.[0]?.message || 'Failed to continue gift subscription, please try again.';
                    throw new Error(errMssg);
                }
                return res.json();
            }).then(function (responseBody) {
                if (responseBody.url) {
                    return window.location.assign(responseBody.url);
                }
                const stripe = window.Stripe(responseBody.publicKey);
                return stripe.redirectToCheckout({
                    sessionId: responseBody.sessionId
                }).then(function (redirectResult) {
                    if (redirectResult.error) {
                        throw new Error(redirectResult.error.message);
                    }
                });
            });
        },

        async checkoutGift({tierId, cadence, duration, email: customerEmail} = {}) {

View on GitHub (pinned to 47d8b0e2ad)

Solutions

  1. Read the concrete thrown message — if it isn't the generic fallback, it carries the backend's reason (e.g. 'Tier not found').
  2. Confirm the currently-signed-in member is the same one who redeemed the gift (identity mismatch is common after switching accounts).
  3. Re-open the gift redemption flow from the original link to obtain a fresh continueFromGift context.
  4. Verify the destination tier/price still exists in Ghost Admin → Settings → Membership.
  5. Check Ghost server logs for the members stripe-checkout-session handler error.
Defensive patterns

Strategy: try-catch

Type guard

function isMembersApiErrorBody(x) {
    return typeof x === 'object' && x !== null && Array.isArray(x.errors) && typeof x.errors[0]?.message === 'string';
}

Try / catch

try {
    await api.member.continueGiftCheckout();
} catch (err) {
    showToast(err.message);
    // Re-open the gift redemption link if identity/tier context is stale
}

Prevention

When it happens

Trigger: A recipient who redeemed a gift subscription chooses to convert/upgrade it; the backend refuses — e.g. the gift redemption no longer maps to a valid member, the target tier is retired, Stripe customer record is missing, or the identity token doesn't match the gift recipient.

Common situations: Gift redemption link was already used or expired; the tier referenced by the gift was deleted/archived after the gift was purchased; member signed in as a different account than the one that redeemed the gift; Stripe customer was deleted in the Stripe dashboard leaving Ghost with a dangling reference.

Related errors


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