payloadcms/payload · error · APIError

Operator handler "${handler.name}" requires the "${extension

Error message

Operator handler "${handler.name}" requires the "${extensionName}" Postgres extension, which is not installed on this database. Add it to the adapter's "extensions" option, or install it manually with CREATE EXTENSION.

What it means

A connection-time `APIError` from `assertOperatorHandlerExtensionsInstalled`: a registered Postgres operator handler declares a `requiredExtensions` entry (e.g. the built-in `postgres-unaccent` handler needs `unaccent`) but that extension is not present in `pg_extension`. The check runs after `createExtensions`, so declaring the extension in the adapter `extensions` option would have installed it automatically; the throw means neither declaration nor manual install happened.

Source

Thrown at packages/drizzle/src/postgres/query/assertOperatorHandlerExtensionsInstalled.ts:37

  drizzle,
  operatorHandlers,
}: Args): Promise<void> => {
  const requiredExtensionsByHandler = operatorHandlers.flatMap((handler) =>
    (handler.requiredExtensions ?? []).map((extensionName) => ({ extensionName, handler })),
  )

  if (!requiredExtensionsByHandler.length) {
    return
  }

  const { rows: installedExtensionRows } = await drizzle.execute<{ extname: string }>(
    sql`SELECT extname FROM pg_extension`,
  )
  const installedExtensions = new Set(installedExtensionRows.map((row) => row.extname))

  for (const { extensionName, handler } of requiredExtensionsByHandler) {
    if (!installedExtensions.has(extensionName)) {
      throw new APIError(
        `Operator handler "${handler.name}" requires the "${extensionName}" Postgres extension, which is not installed on this database. Add it to the adapter's "extensions" option, or install it manually with CREATE EXTENSION.`,
      )
    }
  }
}

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Add the extension to the adapter's `extensions` option so Payload installs it on connect, e.g. `extensions: { unaccent: true }`.
  2. Alternatively install the extension manually: `CREATE EXTENSION IF NOT EXISTS unaccent;`.
  3. Ensure the DB role has CREATE privilege for extensions (or pre-install as superuser).
  4. If you don't actually need the handler, remove it from `operatorHandlers`.

Example fix

// before
new PostgresAdapter({
  pool,
  postgresQuery: { operatorHandlers: [postgresUnaccent()] },
})
// after
new PostgresAdapter({
  pool,
  extensions: { unaccent: true },
  postgresQuery: { operatorHandlers: [postgresUnaccent()] },
})
Defensive patterns

Strategy: validation

Validate before calling

// Before connecting, ensure every handler extension is declared
const required = (operatorHandlers ?? [])
  .flatMap(h => h.requiredExtensions ?? [])
const declared = Object.keys(adapterOptions.extensions ?? {})
const missing = required.filter(e => !declared.includes(e))
if (missing.length) {
  throw new Error(`Declare these extensions on the adapter: ${missing.join(', ')}`)
}
new PostgresAdapter(adapterOptions)

Type guard

const handlerRequiresExtension = (h): h is { requiredExtensions: string[] } =>
  Array.isArray(h?.requiredExtensions) && h.requiredExtensions.length > 0

Try / catch

try {
  await payload.db.init()
} catch (err) {
  if (/requires the ".*" Postgres extension/.test(String(err?.message))) {
    payload.logger.error('Add the missing extension to the adapter extensions option or run CREATE EXTENSION.')
  }
  throw err
}

Prevention

When it happens

Trigger: Configuring `postgresQuery.operatorHandlers` (e.g. `postgresUnaccent()`) without listing the matching extension in the adapter `extensions` option, against a database where that extension isn't pre-installed. Also when an operator handler from a plugin/custom code declares `requiredExtensions` the DB doesn't satisfy.

Common situations: Using accent-insensitive search (`postgresUnaccent`) on a managed Postgres without the `unaccent` extension; deploying to a fresh DB; a custom operator handler requiring `pg_trgm`/`fuzzystrmatch` without declaring it.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/47a4258f88fc423c. Report an issue: GitHub.