Skip to content

Conversation

srini-abhiram
Copy link

@srini-abhiram srini-abhiram commented Sep 17, 2025

When running db pull, the schema diff was incorrectly including functions from the extensions schema, such as grant_pg_cron_access. This would generate a migration file that fails to apply locally due to permission errors, as these functions are owned by system roles. By adding extensions to the list of managed schemas, the CLI's diffing logic now correctly handles these objects, preventing it from generating migrations for platform-level functions. This resolves the local must be owner error.

What kind of change does this PR introduce?

Bug fix

What is the current behavior?

When a user runs supabase db pull, the command generates a migration file that includes CREATE OR REPLACE statements
for functions within the extensions schema (e.g., grant_pg_cron_access). When the user attempts to apply this migration to their local database (for example, by running supabase db reset), it fails with a permission error: ERROR: must be owner of function... (SQLSTATE 42501). This blocks the user's workflow, forcing them to manually remove these statements from the migration file each time they pull from the remote database (trivial task for fewer migrations but tedious task for bigger ones) as mentioned in #4163

What is the new behavior?

With this change, supabase db pull now correctly identifies the extensions schema as a schema managed by Supabase. As a result, it no longer includes platform-level functions from this schema in the user-facing migration file.
The db pull command now completes successfully without generating a migration that will fail on local execution.

Additional context

The fix was implemented by adding "extensions" to the internal list of managedSchemas in internal/db/pull/pull.go. This ensures the CLI's diffing engine treats the extensions schema with the same rules as other Supabase-managed schemas like auth and storage, resolving the root cause of the bug.

When running db pull, the schema diff was incorrectly including functions from the extensions schema, such as grant_pg_cron_access. This would generate a migration file that fails to apply locally due to permission errors, as these functions are owned by system roles. By adding extensions to the list of managed schemas, the CLI's diffing logic now correctly handles these objects, preventing it from generating migrations for platform-level functions. This resolves the local must be owner error.
@srini-abhiram srini-abhiram requested a review from a team as a code owner September 17, 2025 03:34
@coveralls
Copy link

coveralls commented Sep 17, 2025

Pull Request Test Coverage Report for Build 17787501473

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 3 of 3 (100.0%) changed or added relevant lines in 1 file are covered.
  • 7 unchanged lines in 2 files lost coverage.
  • Overall coverage decreased (-0.02%) to 54.775%

Files with Coverage Reduction New Missed Lines %
internal/storage/rm/rm.go 2 80.61%
internal/gen/keys/keys.go 5 12.9%
Totals Coverage Status
Change from base Build 17764974097: -0.02%
Covered Lines: 6280
Relevant Lines: 11465

💛 - Coveralls

Copy link
Contributor

@sweatybridge sweatybridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you check if the problem is reproducible on the experimental flag?

npx supabase@beta --experimental db pull

We want to diff user created entities in extensions schema so this fix won't be sufficient.

@srini-abhiram
Copy link
Author

Yes, I think its reproducible on the experimental flag. with db pull. The flag doesn't seem to change the relevant code path. I might have to re think the solution, thanks for pointing it out.

@srini-abhiram
Copy link
Author

I can see that in the migra diff logic, there is a list of schemas to exclude, but we can't (user-created entites should be diffed). Migra tool itself has no support for excluding functions (in original repo), but cli is using supabase/migra fork. I might have to write a wrapper or extension for the two functions mentioned. This will work as a temporary fix. Is that fine?
If there is support for exclude functions in the fork, then we can use that, but I don't see it. @sweatybridge

When running supabase db pull, migra generates CREATE OR REPLACE statements for the extensions.grant_pg_cron_access() and extensions.grant_pg_net_access() functions. These statements cause errors when running the migration locally, as the local postgres user is not the owner of these functions. 
This change filters the output of the migra diff to remove these two specific function definitions. This prevents the ownership errors while still allowing user-created entities in the extensions schema to be diffed and tracked in migrations.
@sweatybridge
Copy link
Contributor

@srini-abhiram before we spend more time on this solution, could you confirm whether your local postgres version matches the remote database? The grant_pg_cron_access function comes from our upstream postgres image, so you shouldn't see any diff if the postgres versions match.

supabase link
supabase db pull

@srini-abhiram
Copy link
Author

No, my local image is behind the remote version. db pull is generating diffs for functions. I think it does so for major version changes i,e. 4.x.x -> 5.x.x ? Im not sure. But after I remove the create functions block and migrate successfully, I don't see it generated again.

@srini-abhiram
Copy link
Author

srini-abhiram commented Sep 17, 2025

My understanding is this:
The shadow database is created with an older version of the gran_pg_cron_access function from local docker image. But the remote db has a newer (possibly updated) version of the function if supabase platform was updated. Migra then compares the actual code inside functions, sees a mismatch and generated the CREATE OR REPLACE FUNCTION statements.

@srini-abhiram
Copy link
Author

If there is a way to fetch the remote version, we could use the remote version as the shadow db, then apply migrations, thus eliminating the CREATE OR REPLACE FUNCTION code blocks. But it would require us to download the newer image and might lead to generating migration files that use new features the local database doesn't support, possibly breaking the current user implementations. This is a dilemma.

@srini-abhiram
Copy link
Author

srini-abhiram commented Sep 17, 2025

One more solution we could try:
Add a flag to migra, ignoring functions that don't belong to you(owner is postgres, supabase_admin, supabase_storage_admin).
something like migra diff --ignore-owner supabase_admin
This is better than the regex fix.

@sweatybridge
Copy link
Contributor

The shadow database is created with an older version of the gran_pg_cron_access function from local docker image. But the remote db has a newer (possibly updated) version of the function if supabase platform was updated. Migra then compares the actual code inside functions, sees a mismatch and generated the CREATE OR REPLACE FUNCTION statements.

Yes, that's my understanding too. Running supabase link will sync up your local image version with remote.

But it would require us to download the newer image and might lead to generating migration files that use new features the local database doesn't support, possibly breaking the current user implementations. This is a dilemma.

I don't think this is a dilemma because your local database should always be on the same version as the remote database. Otherwise, there's no guarantee that your local migrations will work the same way as on the remote database.

@srini-abhiram
Copy link
Author

there's no guarantee that your local migrations will work the same way as on the remote database.

True. The dilemma I was talking about is less of a dilemma and more of a trade-off. Users would be accustomed, and if they see that migrations are failing, they might go into a state of panic. Especially freshers like me. If we use the remote version as shadow db it would be less permissive (it would correctly fail when inconsistencies are found between local and remote), forcing the devs to fix the issues instead of letting them slide XD. But that is the best solution I could think of.

But I am not sure how to get the remote version. I would be happy to implement this if you can give me some advice. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants