Postgres Error: 'type "..." does not exist' — Cause, Fix, and Troubleshooting Guide
Fix Postgres 'type "citext" does not exist': CREATE EXTENSION, search_path, schema-qualify the type, create enums before use.
- #postgres
- #postgresql
- #database
- #troubleshooting
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 ascitext.
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 EXTENSIONis per-database — installingcitextinpostgresdoes nothing forappdb; 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) makesCREATE EXTENSION citextfail with a different error. - Putting extensions on a shared
extensionsschema keepspublicclean, but every consumer then needs that schema onsearch_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.
Related
- Postgres Error: ‘relation does not exist’
- Postgres Error: ‘column does not exist’
- Postgres Error: ‘role ”…” does not exist’
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?
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.