overleaf/overleaf · error · ManuallyCollectedError
This subscription is being collected manually
Error message
This subscription is being collected manually
What it means
ManuallyCollectedError is thrown by ensureSubscriptionCollectionMethodIsNotManual when a payment-provider subscription has its collection method set to manual, meaning invoices are collected outside the automated billing flow. The app refuses to operate on such subscriptions through the normal automated path. It carries the payment provider's subscription id as metadata.
Source
Thrown at services/web/app/src/Features/Subscription/SubscriptionGroupHandler.mjs:93
async function ensureFlexibleLicensingEnabled(plan) {
if (!plan?.canUseFlexibleLicensing) {
throw new Error('The group plan does not support flexible licensing')
}
}
async function ensureSubscriptionIsActive(subscription) {
if (SubscriptionHelper.getPaidSubscriptionState(subscription) !== 'active') {
throw new InactiveError('The subscription is not active', {
subscriptionId: subscription._id.toString(),
})
}
}
async function ensureSubscriptionCollectionMethodIsNotManual(
paymentProviderSubscription
) {
if (paymentProviderSubscription.isCollectionMethodManual) {
throw new ManuallyCollectedError(
'This subscription is being collected manually',
{
subscription_id: paymentProviderSubscription.id,
}
)
}
}
async function ensureSubscriptionHasNoPastDueInvoice(subscription) {
const [paymentRecord] = await Modules.promises.hooks.fire(
'getPaymentFromRecord',
subscription
)
if (paymentRecord.account.hasPastDueInvoice) {
throw new HasPastDueInvoiceError(
'This subscription has a past due invoice',
{View on GitHub (pinned to 28ad3b03b7)
Solutions
- Change the subscription's collection method to automatic in the payment provider dashboard (or via provider API: subscription.collection_method = 'charge_automatically') before retrying.
- Handle manually-collected subscriptions through the invoicing/enterprise workflow instead of the automated group-management endpoints.
- If this is a transient sync issue, refresh the subscription data from the payment provider and confirm isCollectionMethodManual is actually false before calling.
Example fix
// before
await ensureSubscriptionCollectionMethodIsNotManual(stripeSubscription)
// after
const fresh = await getSubscriptionFromProvider(subscription.id)
if (fresh.isCollectionMethodManual) {
await setCollectionMethodAutomatic(subscription.id) // provider API call
}
await ensureSubscriptionCollectionMethodIsNotManual(fresh) Defensive patterns
Strategy: try-catch
Validate before calling
// before calling
const sub = await getSubscriptionFromProvider(subscriptionId)
if (sub.isCollectionMethodManual) {
throw new SkipError('manually-collected; use invoicing workflow')
} Type guard
const isAutomaticallyCollected = sub => sub.isCollectionMethodManual === false
Try / catch
try {
await ensureSubscriptionCollectionMethodIsNotManual(sub)
} catch (e) {
if (e.name === 'ManuallyCollectedError') {
logger.warn({ subscriptionId: e.info?.subscription_id }, 'manual collection')
return routeToInvoicingWorkflow(sub)
}
throw e
} Prevention
- Check collection_method right after fetching the subscription and branch before mutating calls.
- Keep manually-collected (invoiced) subscriptions in a separate ops workflow, not the self-serve API.
- Alert on subscriptions that flip collection method unexpectedly in provider webhooks.
When it happens
Trigger: Any code path that calls ensureSubscriptionCollectionMethodIsNotManual with a paymentProviderSubscription where paymentProviderSubscription.isCollectionMethodManual is true — e.g. attempting to change plan, add seats, or process automated billing for a manually-collected (invoiced) subscription.
Common situations: Enterprise/invoiced subscriptions created with manual collection in the payment provider (e.g. Stripe collection_method=charge_automatically vs send_invoice); admins trying to apply automated changes to an invoiced team subscription; migration scripts syncing subscriptions where collection method drifted.
Related errors
- This subscription is being collected manually has no "additi
- This subscription has a past due invoice
- subtotal_limit_exceeded
- Subscription already has add-on
- Subscription does not have add-on to update
AI-assisted analysis of overleaf/overleaf@28ad3b03b7 (2026-09-03).
Data as JSON: /api/errors/0448ad73c34ef1cc.
Report an issue: GitHub.