Skip to content
🎉 Launch sale:50% off everything over $22 — automatically applied at checkout· ends Aug 2Shop the sale →
DevOps AI ToolKit
Newsletter
All guides
AI for Postgres By James Joyner IV · · 8 min read Last reviewed Jul 2026

Postgres Error: 'type "..." does not exist' — Cause, Fix, and Troubleshooting Guide

Quick answer

Fix Postgres 'type "citext" does not exist': CREATE EXTENSION, search_path, schema-qualify the type, create enums before use.

Part of the PostgreSQL Database Errors hub
  • #postgres
  • #postgresql
  • #database
  • #troubleshooting
Free toolkit

Stuck on this Postgres error? Get the free incident triage checklist

A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.

Overview

PostgreSQL raises this error when a statement references a data type the current session cannot resolve. The type name is not a built-in, is not provided by an installed extension, or lives in a schema that is not on the search_path.

ERROR:  type "citext" does not exist
LINE 1: CREATE TABLE users (email citext NOT NULL);

Postgres resolves type names the same way it resolves tables: by scanning the schemas on search_path. If nothing on the path defines citext — because the extension was never installed, or it lives in a schema you are not looking in — the type is simply unknown.

Symptoms

  • CREATE TABLE, CREATE FUNCTION, or a migration fails naming a specific type (citext, hstore, uuid, or a custom enum).
  • The type works in one database or schema but not another.
  • A dump restores partially, then fails on a table that uses an extension type.
  • A quoted type name fails on case: "CIText" is not the same as citext.
CREATE TABLE users (email citext NOT NULL);
ERROR:  type "citext" does not exist
LINE 1: CREATE TABLE users (email citext NOT NULL);

Common Root Causes

1. The extension providing the type is not installed

Types like citext and hstore ship as extensions and must be created per-database before use.

SELECT extname FROM pg_extension WHERE extname = 'citext';

An empty result means the extension — and therefore the type — is absent from this database.

2. The type lives in a schema not on search_path

Extensions are often installed into a dedicated extensions schema. If that schema is not on search_path, the unqualified type name will not resolve.

SHOW search_path;
SELECT n.nspname, t.typname
FROM pg_type t
JOIN pg_namespace n ON n.oid = t.typnamespace
WHERE t.typname = 'citext';

3. A custom enum or composite type was never created

Referencing order_status before running its CREATE TYPE — or creating it in a different database — leaves it undefined.

SELECT typname FROM pg_type WHERE typname = 'order_status';

4. The type was dropped by a migration

A DROP TYPE (or DROP EXTENSION ... CASCADE) removed it, and a later statement still expects it. Migration ordering matters.

5. Case sensitivity of quoted type names

Unquoted identifiers fold to lowercase; a quoted "CIText" is a distinct, non-existent name.

How to diagnose

Step 1: Ask the catalog whether the type exists

SELECT n.nspname AS schema, t.typname AS type
FROM pg_type t
JOIN pg_namespace n ON n.oid = t.typnamespace
WHERE t.typname = 'citext';
 schema | type
--------+------
(0 rows)

Zero rows means the type is not defined anywhere in this database. In psql, \dT citext gives the same answer interactively.

Step 2: Check installed extensions

SELECT extname, extnamespace::regnamespace AS schema
FROM pg_extension
ORDER BY extname;

In psql, \dx lists them. If citext is missing, the type cannot exist yet.

Step 3: Confirm the search_path

SHOW search_path;
   search_path
-----------------
 "$user", public
(1 row)

If the extension lives in an extensions schema not listed here, that is why an unqualified reference fails.

Fixes

Install the extension

For built-in extension types, one statement per database is enough:

CREATE EXTENSION IF NOT EXISTS citext;
CREATE TABLE users (email citext NOT NULL);

hstore, uuid-ossp, and pgcrypto (for gen_random_uuid()) follow the same pattern.

Schema-qualify the type

If the type exists but in another schema, name it explicitly:

CREATE TABLE users (email extensions.citext NOT NULL);

Add the schema to search_path

So future unqualified references resolve, put the extension schema on the path:

ALTER DATABASE appdb SET search_path TO "$user", public, extensions;

New sessions pick this up; reconnect for it to take effect.

Create custom types before they are used

Define enums and composites ahead of the tables and functions that reference them:

CREATE TYPE order_status AS ENUM ('pending', 'paid', 'shipped', 'cancelled');
CREATE TABLE orders (id bigserial PRIMARY KEY, status order_status NOT NULL);

Fix migration ordering

Ensure the migration that creates the extension or type runs before any migration that references it, and that DROP statements are not stranded ahead of dependents.

What to watch out for

  • CREATE EXTENSION is per-database — installing citext in postgres does nothing for appdb; run it in every database that needs the type.
  • Restoring a dump requires the extension to be creatable on the target; a missing contrib package (postgresql-contrib) makes CREATE EXTENSION citext fail with a different error.
  • Putting extensions on a shared extensions schema keeps public clean, but every consumer then needs that schema on search_path.
  • Quoted type names are case-sensitive — write citext, not "Citext", unless you truly created a mixed-case type.
  • Enum values cannot be removed later without recreating the type; plan the enum before you depend on it widely.
Free download · 368-page PDF

Fixed it? Get 500 Postgres & DevOps AI prompts — free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.

Did this fix your issue?

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.