Skip to content

Hosted Data API can keep non-existent public/api schemas in PostgREST db-schemas after dashboard exposed-schema changes #45904

Description

@lastmjs

Bug report

Describe the bug

In a hosted Supabase project, the Dashboard Integrations > Data API > Settings > Exposed schemas value can appear to be updated to custom schemas only, while the running PostgREST process still tries to build its schema cache with non-existent schemas such as public or a previously exposed custom schema.

This breaks the Data API entirely because PostgREST fails schema-cache loading with SQLSTATE 3F000 before serving RPC requests.

This looks related to, but different from, issues such as #40617 and #43723. In this case the project intentionally does not have a public schema, the Dashboard Data API settings were saved repeatedly with only custom schemas, and toggling the Data API off/on did not reliably clear the runtime db-schemas value.

Sanitized PostgREST logs

Example after removing a legacy api schema from exposed schemas and saving the Dashboard Data API settings:

{
  "event_message": "Failed to load the schema cache using db-schemas=api,agent_api,ai_api,auth_api,human_api,machine_api and db-extra-search-path=extensions. {\"code\":\"3F000\",\"details\":null,\"hint\":null,\"message\":\"schema \\\"api\\\" does not exist\"}"
}

Example after resetting/toggling the Data API settings in the Dashboard:

{
  "event_message": "Failed to load the schema cache using db-schemas=public,auth_api,human_api and db-extra-search-path=extensions. {\"code\":\"3F000\",\"details\":null,\"hint\":null,\"message\":\"schema \\\"public\\\" does not exist\"}"
}

All project refs, hostnames, request ids, and event ids have been removed from these examples.

Database state

A read-only SQL check showed that only the custom API schemas existed and both api and public did not exist:

select
  schema_name,
  to_regnamespace(schema_name) is not null as schema_exists
from (
  values
    ('api'),
    ('public'),
    ('agent_api'),
    ('ai_api'),
    ('auth_api'),
    ('human_api'),
    ('machine_api')
) as target(schema_name);

Result:

api         false
public      false
agent_api   true
ai_api      true
auth_api    true
human_api   true
machine_api true

To Reproduce

The exact platform-side reproduction is unclear, but the project state was:

  1. Hosted Supabase project using custom Data API schemas only.
  2. public schema intentionally absent.
  3. A previously exposed legacy schema, api, was dropped as part of a migration/refactor.
  4. Dashboard Integrations > Data API > Settings > Exposed schemas was updated and saved to include only custom schemas.
  5. Dashboard was used multiple times to save/reset the schema list and to disable/re-enable the Data API.
  6. PostgREST logs still showed runtime db-schemas containing either the deleted api schema or the absent public schema.
  7. Data API calls returned 500 because PostgREST could not load the schema cache.

Expected behavior

When the Dashboard Data API exposed schemas are saved, the running PostgREST config should stop including schemas that are no longer listed. If public is absent and not listed in exposed schemas, PostgREST should not automatically include public in db-schemas.

Disabling/re-enabling the Data API or saving exposed schemas should reload the effective PostgREST config, or the Dashboard should surface that a database-level authenticator override or platform-managed config is taking precedence.

Actual behavior

The Dashboard showed the intended exposed schemas, but PostgREST continued trying to build the schema cache with missing schemas. This caused Data API/RPC calls to fail with 500 responses and PGRST002 in application-level clients.

Workaround

Explicitly setting the PostgREST schema list on the authenticator role fixed the issue:

alter role authenticator set pgrst.db_schemas = 'agent_api,ai_api,auth_api,human_api,machine_api';
notify pgrst, 'reload config';
notify pgrst, 'reload schema';

Optionally setting the extra search path explicitly also worked as expected:

alter role authenticator set pgrst.db_extra_search_path = 'extensions';

This workaround is effective, but it creates an explicit database-level override that may diverge from the Dashboard setting, which is surprising for hosted Supabase users.

Additional context

It would be helpful if the hosted Dashboard either:

  • reliably propagated Exposed schemas to the effective PostgREST db-schemas,
  • showed the effective pgrst.db_schemas value when it differs from the Dashboard value,
  • warned that a role/database-level override is taking precedence, or
  • provided a visible way to reload/reset the effective PostgREST config.

Metadata

Metadata

Assignees

No one assigned

    Labels

    databasePostgres and all-things-databaseexternal-issueCreated outside of SupabasefrontendRelated to Supabase DashboardpostgRESTRelated to PostgREST

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions