Budibase/budibase · error · HTTPError

License key has already been activated

Error message

License key has already been activated

What it means

Thrown by activateLicenseKey when POST /api/license/activate responds with 409 Conflict — the license key has already been activated against another (or the same) installation. The portal enforces one activation per key, so re-activating the same key elsewhere conflicts with the existing binding.

Source

Thrown at packages/pro/src/sdk/licensing/licenses/client.ts:243

  const body: LicenseActivateRequest = {
    installVersion: install.version,
    installId: install.installId,
  }

  const response = await api.post(`/api/license/activate`, {
    headers: {
      [constants.Header.LICENSE_KEY]: licenseKey,
    },
    body,
  })

  // don't propagate the 403 to prevent logout
  if (response.status === 403) {
    throw new HTTPError("Invalid license key", 400)
  }

  if (response.status === 409) {
    throw new HTTPError("License key has already been activated", 409)
  }

  if (response.status !== 200) {
    const message = await getResponseErrorMessage(response)
    throw new HTTPError(
      `Error activating license key: ${message}`,
      response.status
    )
  }

  return response.json()
}

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Check if the key is already active on this install — if the install already works, skip activation and just fetch the license.
  2. Deactivate the license on the old installation (or via the account portal) before reactivating on the new one.
  3. Contact Budibase support to reset the activation binding if the old install is gone/unrecoverable.
  4. Use a distinct license key per environment (dev/staging/prod) instead of sharing one key.

Example fix

// before
await activateLicenseKey(key) // throws 409 on retry
// after
try {
  await activateLicenseKey(key)
} catch (e) {
  if (e instanceof HTTPError && e.status === 409) {
    console.warn("Key already activated — fetching existing license instead")
    await getLicenseFromKey(key)
  } else {
    throw e
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before activating, check whether this install already has a working license
const existing = await getLicenseFromKey(key)
if (existing) { /* already activated — skip activateLicenseKey */ }

Type guard

function isAlreadyActivated(e: unknown): boolean {
  return e instanceof HTTPError && e.status === 409
}

Try / catch

try {
  await activateLicenseKey(key)
} catch (e) {
  if (isAlreadyActivated(e)) {
    // treat as success or fetch existing license instead of rethrowing
  } else throw e
}

Prevention

When it happens

Trigger: Calling activateLicenseKey(licenseKey) for a key already bound to an installId — e.g. activating on a second environment, re-running activation after a restore with a changed installId, or a stale portal record.

Common situations: Migrating Budibase to a new server without deactivating the old one; restoring a backup where the installId changed; CI/test environments sharing a production license key; duplicate activation attempts after a network timeout that actually succeeded.

Related errors


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