Budibase/budibase · error · HTTPError

OAuth2 config with id '${config._id}' not found.

Error message

OAuth2 config with id '${config._id}' not found.

What it means

When updating an OAuth2 configuration via sdk.workspace.oauth2.update, the SDK first re-reads the existing config document from the workspace DB with get(config._id). If no document exists with that id, it throws this 404 HTTPError. It exists so a stale or fabricated config object cannot be silently upserted over a deleted config.

Source

Thrown at packages/server/src/sdk/workspace/oauth2/crud.ts:74

    _rev: response.rev!,
    ...config,
  }
}

export async function get(id: string): Promise<OAuth2Config | undefined> {
  const db = context.getWorkspaceDB()
  return await db.tryGet(id)
}

export async function update(
  config: CreatedOAuthConfig
): Promise<CreatedOAuthConfig> {
  const db = context.getWorkspaceDB()
  await guardName(config.name, config._id)

  const existing = await get(config._id)
  if (!existing) {
    throw new HTTPError(`OAuth2 config with id '${config._id}' not found.`, 404)
  }

  const toUpdate = {
    ...config,
    clientSecret:
      config.clientSecret === PASSWORD_REPLACEMENT
        ? existing.clientSecret
        : config.clientSecret,
  }

  const result = await db.put(toUpdate)

  await cleanCache(config._id)

  return { ...toUpdate, _rev: result.rev }
}

export async function remove(configId: string, _rev: string): Promise<void> {

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Re-fetch the config list (sdk fetch()) and confirm the _id exists before updating
  2. Call create() instead of update() when the config does not exist yet
  3. Verify you are running in the correct workspace context (getWorkspaceDB)
  4. Refresh the client-side state so you are not editing a deleted config

Example fix

// before
await sdk.workspace.oauth2.update({ ...staleConfig, name: 'renamed' })
// after
const existing = await sdk.workspace.oauth2.get(staleConfig._id)
if (!existing) {
  const created = await sdk.workspace.oauth2.create({ name: 'renamed', ...rest })
} else {
  await sdk.workspace.oauth2.update({ ...staleConfig, name: 'renamed' })
}
Defensive patterns

Strategy: validation

Validate before calling

const configs = await sdk.workspace.oauth2.fetch()
if (!configs.some(c => c._id === config._id)) {
  throw new Error(`OAuth2 config ${config._id} no longer exists; recreate before updating`)
}

Type guard

function isExistingConfig(
  c: CreatedOAuthConfig | undefined
): c is CreatedOAuthConfig {
  return !!c && typeof c._id === "string" && typeof c._rev === "string"
}

Try / catch

try {
  await sdk.workspace.oauth2.update(config)
} catch (e) {
  if (e instanceof HTTPError && e.status === 404) {
    // recreate or surface 'config was deleted'
  } else throw e
}

Prevention

When it happens

Trigger: Calling update(config) with a CreatedOAuthConfig whose _id does not exist in the current workspace DB — e.g. the config was deleted by another user/process, the id is wrong or belongs to another workspace, or the caller passes a fabricated/hardcoded id.

Common situations: Stale UI after two admins delete/edit the same config concurrently; copying config ids between dev/prod workspaces; passing an id without the oauth2 config doc-id prefix; restoring a workspace from backup without the config docs.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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