org.postgresql.util.PSQLException ERROR relation app_user does not exist
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
When PostgreSQL says relation "app_user" does not exist, it is not making a vague complaint. It is telling you that the name in your SQL could not be resolved to a visible table, view, sequence, or similar relation. In application code, the real cause is usually one of four things: wrong schema, wrong identifier case, missing migration, or connection to the wrong database.
What PostgreSQL Means by "Relation"
PostgreSQL uses the word relation broadly. Tables are relations, but so are views, materialized views, indexes, and sequences. In the common application case, though, this error usually means the table name in the query is not visible from the current session.
For example:
PostgreSQL resolves app_user against the current schema search path. If no matching relation is visible there, the server raises the error and the JDBC driver surfaces it as PSQLException.
First Check Schema and Search Path
The table may exist, just not in the schema you are searching.
Start with direct inspection:
If the query shows auth.app_user, then the table exists but is not visible through the current search_path. In that case, the safest fix is often to qualify the name explicitly:
This removes ambiguity and makes application SQL more predictable.
Identifier Case Can Break Matching
PostgreSQL folds unquoted identifiers to lowercase. That means:
- '
app_userbecomes lowercase automatically' - '
"App_User"stays exactly mixed case'
So this table:
must always be referenced with the exact quoted name:
If your query uses app_user without quotes, PostgreSQL will not match the mixed-case table. This is why many teams use only lowercase, unquoted identifiers.
The Table May Not Exist in This Database
Another very common cause is environment mismatch. Migrations may have been applied in development but not in test. Or the application may be pointed at a different database than the one you are inspecting in a GUI tool.
That is why one of the first debugging steps should be to log the connection details and confirm:
- host
- port
- database name
- current user
- current schema assumptions
If you do not confirm the actual target database, you can waste a lot of time looking at the wrong place.
Check the SQL Your Java Code Really Sends
ORMs and query builders can hide the physical table name. Naming strategies, pluralization, default schemas, and quoted identifiers may all alter the generated SQL.
A plain JDBC example makes the issue concrete:
If the schema is known, explicit qualification like auth.app_user is often the least surprising option.
Migrations Are Often the Real Fix
When the table truly does not exist, the fix is not to change SQL until it works. The fix is to make sure the migration that creates app_user ran successfully in the target environment.
Check your migration tool logs, schema history table, or startup migration step. With Flyway or Liquibase, failures during deployment often leave the application running against a partially initialized database.
Common Pitfalls
- Assuming the table is absent before checking schema and search path.
- Forgetting that quoted PostgreSQL identifiers are case-sensitive.
- Looking at one database in a tool while the application is connected to another.
- Trusting ORM entity names instead of logging the actual SQL sent to PostgreSQL.
- Fixing symptoms in application code when the real problem is a migration that never ran.
Summary
- '
relation "app_user" does not existusually means wrong schema, wrong case, missing migration, or wrong database.' - Check
pg_tables,search_path, and the current database before changing code. - Prefer schema-qualified names when multiple schemas are possible.
- Avoid mixed-case quoted identifiers unless you truly want permanent exact-name handling.
- If the table is genuinely missing, fix the migration or deployment path instead of masking the error.
Related reading
- org.postgresql.util.PSQLException FATAL sorry, too many clients already
- Orient DB distributed replica on embedded server
- Pagination between separated data
- Paging Resultsets in Cassandra with compound primary keys - Missing out on rows
- org.springframework.web.client.HttpClientErrorException 400 Bad Request
- org.xerial.snappy.SnappyError [FAILED_TO_LOAD_NATIVE_LIBRARY] no native library is found for os.name=Mac and os.arch=aarch64
- pandas loc vs. iloc vs. at vs. iat?
- pandas multiple conditions while indexing data frame - unexpected behavior

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.