PostgreSQL raises ERROR: <name> is not a table (or similar) with SQLSTATE 42809 and condition name wrong_object_type when a DDL or DML command targets an object of an incompatible type. For example, you'll see this error if you attempt ALTER TABLE on a view, VACUUM a sequence, or use TRUNCATE on a foreign table that does not support it.
What This Error Means
SQLSTATE 42809 belongs to error class 42 — "Syntax Error or Access Rule Violation." Despite the class name, wrong_object_type is not a syntax error; it means the SQL is syntactically valid but semantically incorrect because the named object exists yet is of the wrong kind for the requested operation.
PostgreSQL's catalog stores all database objects (tables, views, sequences, materialized views, foreign tables, indexes, composite types, etc.) in pg_class and related system catalogs. When you execute a command, PostgreSQL looks up the object by name, finds it, and then checks whether its relkind (or equivalent attribute) matches what the command requires. If the kinds do not match, it raises 42809 before any data access occurs.
The transaction is not automatically aborted by this error — the connection remains open — but any ongoing explicit transaction will be in an aborted state and must be rolled back before further work can proceed. Because the command never executes, no data is modified.
Common Causes
Applying a table-specific DDL command to a view. Commands such as
ALTER TABLE ... ADD COLUMN,CLUSTER, orTRUNCATEdo not apply to views. A view hasrelkind = 'v', not'r'(ordinary table).Using
VACUUMorANALYZEon a non-table object. WhileANALYZEaccepts views in some contexts,VACUUMrequires a plain table or materialized view. AttemptingVACUUMon a sequence or composite type raises this error.Running
ALTER SEQUENCEon a table or view. If a developer mistypes the object name and happens to match a table rather than a sequence, PostgreSQL raises42809rather than42P01(undefined_table).Calling
REINDEX TABLEorCLUSTERon a materialized view or foreign table when the operation requires a specific kind of relation.ORM or migration tool confusion. Code-generation tools or migration frameworks sometimes detect object names without checking
relkind, then emit the wrong DDL variant (e.g., issuingALTER TABLEon an object that was manually replaced with a view).
How to Fix wrong_object_type
Verify the object kind before issuing the command. Query
pg_classto confirm what you are targeting:SELECT relname, relkind FROM pg_class WHERE relname = 'your_object_name' AND relnamespace = 'your_schema'::regnamespace;Common
relkindvalues:r= ordinary table,v= view,m= materialized view,S= sequence,f= foreign table,i= index,c= composite type.Use the correct command for the object type. If the object is a view and you want to add a column, you must redefine the view with
CREATE OR REPLACE VIEWor drop and recreate it. You cannotALTER TABLEa view.-- Wrong: raises 42809 if my_view is a view ALTER TABLE my_view ADD COLUMN new_col integer; -- Correct: recreate the view with the additional expression CREATE OR REPLACE VIEW my_view AS SELECT id, name, 0 AS new_col FROM base_table;Use
ALTER MATERIALIZED VIEWinstead ofALTER TABLEfor materialized views. PostgreSQL provides separate DDL commands for materialized views:-- Wrong ALTER TABLE my_matview SET (autovacuum_enabled = true); -- Correct ALTER MATERIALIZED VIEW my_matview SET (autovacuum_enabled = true);Use
ALTER SEQUENCEfor sequences, notALTER TABLE:-- Correct ALTER SEQUENCE my_seq INCREMENT BY 5;Fix migration scripts that conflate object types. If an ORM emits
ALTER TABLEfor something that is a view in your database (perhaps a table that was later replaced by a view), you need to either restore the underlying table or update the migration to use view-compatible DDL.
Additional Information
- SQLSTATE
42809has been part of PostgreSQL's error catalog since at least PostgreSQL 8.x; the behavior is unchanged in modern versions (PostgreSQL 14–17). - Related SQLSTATE codes in class
42:42P01(undefined_table) — object does not exist at all42710(duplicate_object) — object of that name already exists42501(insufficient_privilege) — object exists and is the right type, but access is denied42601(syntax_error) — syntactically malformed statement
- psycopg2 / psycopg3: raises
psycopg2.errors.WrongObjectType(subclass ofProgrammingError). The SQLSTATE can be read frome.pgcode. - JDBC: surfaces as
org.postgresql.util.PSQLExceptionwithgetSQLState()returning"42809". - SQLAlchemy / Alembic: ORM auto-reflect or
op.alter_column()can trigger this if the target object was manually replaced with a view between migrations. Add an explicitrelkindcheck in the migration'supgrade()function when in doubt. - This error has no performance implications — no data access occurs before it is raised.
Frequently Asked Questions
Why does PostgreSQL say "is not a table" even though the object clearly exists?
PostgreSQL found the object in the catalog but determined its relkind is not 'r' (ordinary table). The object exists — it is just a different kind (view, sequence, materialized view, etc.). Use the pg_class query above to confirm what kind it is.
Can I use ALTER TABLE on a materialized view?
No. Materialized views have their own DDL command: ALTER MATERIALIZED VIEW. Some storage parameters can be set on materialized views this way, but column-level changes require dropping and recreating the materialized view.
My migration tool generated ALTER TABLE for an object that used to be a table but is now a view. What should I do?
You have two options: revert the view back to a table (if that is safe), or rewrite the migration step to use CREATE OR REPLACE VIEW instead of ALTER TABLE. The right choice depends on whether the view was intentional and whether dependent objects exist.
Does this error abort my transaction?
The error itself does not roll back the transaction, but PostgreSQL puts the transaction into an error state. You must issue ROLLBACK (or ROLLBACK TO SAVEPOINT if you used a savepoint) before sending any further commands on that connection. In autocommit mode, there is no explicit transaction to roll back.