overleaf/overleaf · warning · MissingBillingInfoError
This account has no billing info
Error message
This account has no billing info
What it means
RecurlyClient.getPaymentMethod fetches a user's billing info from Recurly. If Recurly returns a NotFoundError for the account's billing info, it throws MissingBillingInfoError — the Recurly account exists the call targets but has no payment method stored on file.
Source
Thrown at services/web/app/src/Features/Subscription/RecurlyClient.mjs:542
*/
async function resumeSubscriptionByUuid(subscriptionUuid) {
return await client.resumeSubscription('uuid-' + subscriptionUuid)
}
/**
* Get the payment method for the given user
*
* @param {string} userId
* @return {Promise<PaymentMethod>}
*/
async function getPaymentMethod(userId) {
let billingInfo
try {
billingInfo = await client.getBillingInfo(`code-${userId}`)
} catch (error) {
if (error instanceof recurly.errors.NotFoundError) {
throw new MissingBillingInfoError('This account has no billing info', {
userId,
})
}
throw error
}
return paymentMethodFromApi(billingInfo)
}
/**
* Get the configuration for a given add-on
*
* @param {string} planCode
* @param {string} addOnCode
* @return {Promise<PaymentProviderAddOn>}
*/
async function getAddOn(planCode, addOnCode) {
const addOn = await client.getPlanAddOn(View on GitHub (pinned to 28ad3b03b7)
Solutions
- Catch MissingBillingInfoError and redirect the user to add billing info before continuing
- Check whether the user has billing info on file (via this call guarded by try/catch) before operations requiring a payment method
- Catch the underlying recurly.errors.NotFoundError if handling at the Recurly client layer
- Verify the userId maps to the correct Recurly account code (code-<userId>) to rule out a lookup against the wrong account
Example fix
// before
const paymentMethod = await recurlyClient.getPaymentMethod(userId)
// after
let paymentMethod
try {
paymentMethod = await recurlyClient.getPaymentMethod(userId)
} catch (err) {
if (err instanceof MissingBillingInfoError) {
return { paymentMethod: null, needsBillingInfo: true }
}
throw err
} Defensive patterns
Strategy: try-catch
Try / catch
try {
const pm = await recurlyClient.getPaymentMethod(userId)
} catch (err) {
if (err instanceof MissingBillingInfoError) {
return { paymentMethod: null, needsBillingInfo: true }
}
throw err
} Prevention
- Treat missing billing info as a normal state, not a crash
- Route users without a payment method to the billing-info form first
- Verify userId maps to the correct Recurly account code
- Cache billing-info presence to reduce NotFound round-trips
When it happens
Trigger: Calling getPaymentMethod(userId) for a Recurly account that has never saved a card/PayPal/billing address, e.g. a user who subscribed via a path that skipped billing-info collection.
Common situations: Group-plan admins who joined but never entered payment details; accounts migrated between providers losing billing info; SSO-created accounts; flows assuming a card on file after plan change.
Related errors
- Subscription already has add-on
- Subscription does not have add-on to update
- Subscription does not have add-on to remove
- Add-on is not pending cancellation
- Subtotal amount in cents exceeded error
AI-assisted analysis of overleaf/overleaf@28ad3b03b7 (2026-09-03).
Data as JSON: /api/errors/16878e9e13e2bd37.
Report an issue: GitHub.