How to Fix PostgreSQL Error: Permission Denied for Schema

The "Permission denied for schema" error occurs when a user tries to access objects within a schema without having the necessary USAGE privilege on that schema. Schemas are namespaces that contain database objects, and PostgreSQL requires explicit schema-level permissions before allowing access to objects within them.

Impact

This error prevents users from accessing any objects (tables, views, functions) within the schema, even if they have permissions on individual objects. It effectively blocks entire sections of the database from user access, causing widespread application failures.

Common Causes

  1. Missing USAGE privilege on the schema
  2. Schema permissions not granted after schema creation
  3. Default privileges not configured for new schemas
  4. Using custom schemas without proper permission setup
  5. Revoked schema access
  6. User attempting to access private schemas
  7. Search path not including the schema

Troubleshooting and Resolution Steps

  1. Check schema permissions:

    -- List all schemas and their privileges
    \dn+
    
    -- Check specific schema permissions
    SELECT nspname, nspacl
    FROM pg_namespace
    WHERE nspname = 'your_schema';
    
  2. Grant USAGE privilege on schema:

    -- Grant schema usage to user
    GRANT USAGE ON SCHEMA your_schema TO username;
    
    -- Grant to multiple users
    GRANT USAGE ON SCHEMA your_schema TO user1, user2, user3;
    
    -- Grant to all users (use with caution)
    GRANT USAGE ON SCHEMA your_schema TO PUBLIC;
    
  3. Grant comprehensive schema access:

    -- Grant schema usage and object access
    GRANT USAGE ON SCHEMA your_schema TO username;
    GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA your_schema TO username;
    GRANT USAGE ON ALL SEQUENCES IN SCHEMA your_schema TO username;
    GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA your_schema TO username;
    
  4. Configure default privileges for future objects:

    -- Set default privileges for tables
    ALTER DEFAULT PRIVILEGES IN SCHEMA your_schema
    GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO username;
    
    -- For sequences
    ALTER DEFAULT PRIVILEGES IN SCHEMA your_schema
    GRANT USAGE ON SEQUENCES TO username;
    
    -- For functions
    ALTER DEFAULT PRIVILEGES IN SCHEMA your_schema
    GRANT EXECUTE ON FUNCTIONS TO username;
    
  5. Set up search_path to include the schema:

    -- Set for current session
    SET search_path TO your_schema, public;
    
    -- Set for specific user permanently
    ALTER USER username SET search_path TO your_schema, public;
    
    -- Set database-wide default
    ALTER DATABASE mydb SET search_path TO your_schema, public;
    
  6. Grant CREATE privilege if user needs to create objects:

    -- Allow creating new objects in schema
    GRANT CREATE ON SCHEMA your_schema TO username;
    
  7. Transfer schema ownership if needed:

    -- Change schema owner
    ALTER SCHEMA your_schema OWNER TO new_owner;
    
  8. Create a role for schema access management:

    -- Create role for schema access
    CREATE ROLE schema_users;
    
    -- Grant permissions to role
    GRANT USAGE ON SCHEMA your_schema TO schema_users;
    GRANT SELECT ON ALL TABLES IN SCHEMA your_schema TO schema_users;
    
    -- Add users to role
    GRANT schema_users TO user1, user2, user3;
    
  9. Check effective permissions:

    -- Check if user has schema usage
    SELECT has_schema_privilege('username', 'your_schema', 'USAGE');
    SELECT has_schema_privilege('username', 'your_schema', 'CREATE');
    
  10. For application setup, grant all necessary schema permissions:

    -- Complete application user setup
    CREATE ROLE app_user WITH LOGIN PASSWORD 'secure_password';
    GRANT CONNECT ON DATABASE mydb TO app_user;
    GRANT USAGE ON SCHEMA public TO app_user;
    GRANT USAGE ON SCHEMA app_schema TO app_user;
    GRANT ALL ON ALL TABLES IN SCHEMA app_schema TO app_user;
    GRANT ALL ON ALL SEQUENCES IN SCHEMA app_schema TO app_user;
    GRANT ALL ON ALL FUNCTIONS IN SCHEMA app_schema TO app_user;
    
    -- Future objects
    ALTER DEFAULT PRIVILEGES IN SCHEMA app_schema
    GRANT ALL ON TABLES TO app_user;
    ALTER DEFAULT PRIVILEGES IN SCHEMA app_schema
    GRANT ALL ON SEQUENCES TO app_user;
    

Additional Information

  • The public schema has USAGE granted to PUBLIC by default
  • Custom schemas require explicit USAGE grants
  • USAGE permission on schema is prerequisite for accessing any objects within
  • Schema ownership doesn't automatically grant access to contained objects
  • Regular audit of schema permissions is important for security
  • Use schemas to organize related objects and implement access control boundaries

Frequently Asked Questions

Q: What's the difference between USAGE and CREATE privileges on a schema?
A: USAGE allows accessing existing objects in the schema, while CREATE allows creating new objects in the schema.

Q: Why can't I access a table even though I have SELECT permission on it?
A: You need both USAGE permission on the schema and SELECT permission on the table. Missing schema USAGE will cause "permission denied for schema" error.

Q: How do I grant access to all schemas?
A: You must grant individually for each schema:

DO $$
DECLARE
  schema_name text;
BEGIN
  FOR schema_name IN SELECT nspname FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema'
  LOOP
    EXECUTE format('GRANT USAGE ON SCHEMA %I TO username', schema_name);
  END LOOP;
END $$;

Q: What is search_path and how does it relate to schemas?
A: search_path defines the order in which PostgreSQL searches schemas for objects. Setting it helps users access objects without schema-qualifying names (e.g., table instead of schema.table).

Q: Can I revoke schema access from a user?
A: Yes, use REVOKE USAGE ON SCHEMA your_schema FROM username; Note that this only affects direct grants, not those inherited from roles.

Q: How do I see all permissions for a schema?
A: Use \dn+ schema_name in psql or query:

SELECT nspname, nspacl
FROM pg_namespace
WHERE nspname = 'your_schema';
Pulse - Elasticsearch Operations Done Right

Pulse can solve your Elasticsearch issues

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.