Budibase/budibase · warning · UsageLimitWarning

${action.name}

Error message

${action.name}

What it means

After computing the new total usage for an action, updateUsage compares it against the licensed quota value. If the quota is not UNLIMITED, the total would exceed the limit, and the usageChange is positive (increment), it throws a UsageLimitWarning whose message is simply the quota action name. Decrementing is deliberately allowed so a tenant can climb back down after exceeding a quota. The thrown name is the quota name, not a human sentence — callers are expected to wrap it.

Source

Thrown at packages/pro/src/sdk/quotas/quotas.ts:388

          }

          let triggers: QuotaTriggers = {}
          if (!action.opts?.dryRun) {
            triggers = await checkTriggers(
              action.type,
              action.name,
              totalValue,
              licensedQuota
            )
            triggersToApply = { ...triggersToApply, [action.name]: triggers }
          }

          if (
            licensedQuota.value !== constants.UNLIMITED &&
            totalValue > licensedQuota.value &&
            action.usageChange > 0 // allow for decrementing usage when the quota is already exceeded
          ) {
            throw new UsageLimitWarning(`${action.name}`)
          }

          // never go negative if the quota has previously been exceeded
          totalValue = Math.max(0, totalValue)
          if (appValue) {
            appValue = Math.max(0, appValue)
          }
          if (breakdownValue != null) {
            breakdownValue = Math.max(0, breakdownValue)
            breakdownValuesToApply = {
              ...breakdownValuesToApply,
              [action.name]: breakdownValue,
            }
          }

          // Apply functions if it is not a dry run
          if (!action.opts?.dryRun) {
            // if a value function is provided

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Free up usage by deleting resources (or wait for monthly reset) before incrementing again
  2. Upgrade the plan/license to raise the specific quota named in the message
  3. Catch UsageLimitWarning and map the quota name to a user-friendly limit message
  4. Review bulk operations to pre-check quota headroom before large imports

Example fix

// before: name-only warning propagates raw
try { await createRows(rows) } catch (e) { throw e }
// after: translate the quota name
try {
  await createRows(rows)
} catch (err) {
  if (err instanceof UsageLimitWarning) {
    throw new Error(`You have reached your ${err.message} quota limit — upgrade to continue`)
  }
  throw err
}
Defensive patterns

Strategy: try-catch

Validate before calling

const current = await quotas.getUsage(action.name)
const limit = await quotas.getLicensedLimit(action.name)
if (limit !== constants.UNLIMITED && current + usageChange > limit) {
  // block operation up-front and show upgrade prompt
}

Try / catch

try {
  await createResource()
} catch (err) {
  if (err instanceof UsageLimitWarning) {
    throw new Error(`Quota limit reached: ${err.message} — upgrade your plan`)
  }
  throw err
}

Prevention

When it happens

Trigger: An increment (e.g. creating rows/users/queries/apps) that would push monthly or static usage past the licensed quota value while usage is already at or above the limit.

Common situations: Free-plan tenant hitting row or user caps; automation bulk-creating records that overshoot a quota mid-run; license downgrade shrinking a quota below current usage so every subsequent increment throws; apps/users import exceeding static quotas.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/74f1c166b108409e. Report an issue: GitHub.