Skip to content

gen types: PostgrestVersion / __InternalSupabase causes false diffs without schema changes #6390

Description

@scs0209

Summary

supabase gen types typescript can produce a different committed file even when the Postgres schema is unchanged. The only diff is often __InternalSupabase.PostgrestVersion.

This makes schema drift checks (CI comparing regenerated types vs committed database.ts) noisy and forces consumers to strip metadata manually.

Motivation / workflow

A common setup:

  1. Local dev: supabase gen types typescript --linked --schema public → commit database.ts
  2. CI (no remote token): supabase start + supabase gen types typescript --local --schema public → compare to committed file

We expect the comparison to answer: “Did migrations / schema change?”

Instead, raw output can differ because of PostgREST version metadata, not because tables/columns changed.

Reproduction

CLI version: 2.116.0 (via npx supabase)

  1. Generate types from a linked project and commit the file:

    npx supabase gen types typescript --linked --schema public > database.ts

    Note __InternalSupabase.PostgrestVersion (e.g. "14.15").

  2. Without changing any migration or remote schema, run the same command again days later:

    npx supabase gen types typescript --linked --schema public > database-fresh.ts
    diff -u database.ts database-fresh.ts
  3. Observed: diff is only:

    -    PostgrestVersion: "14.15"
    +    PostgrestVersion: "14.5"

    Table/column types (public.Tables.*) are identical.

  4. Stripping __InternalSupabase / normalizing PostgrestVersion yields byte-identical schema output.

Why this hurts

  • git diff after gen types suggests a schema update when there was none
  • CI drift checks on raw files false-fail unless consumers add custom normalization
  • Cross-mode checks (--linked vs --local) can differ in metadata even when migrations match

Current workaround

We normalize before compare (strip __InternalSupabase, normalize PostgrestVersion):

const normalize = (src) =>
  src
    .replace(/\r\n/g, '\n')
    .replace(
      /\n\s*\/\/ Allows to automatically instantiate createClient with right options\n\s*\/\/ instead of createClient<Database, \{ PostgrestVersion: 'XX' \}>\(URL, KEY\)\n\s*__InternalSupabase: \{\n\s*PostgrestVersion: "[^"]+"\n\s*\}\n/,
      '\n',
    )
    .replace(/PostgrestVersion:\s*"[^"]+"/g, 'PostgrestVersion: "NORMALIZED"')
    .trimEnd() + '\n';

This works but shouldn’t be required for “schema unchanged” to mean “types output unchanged (modulo metadata)”.

Related

  • postgres-meta #959 (reproducibility)
  • postgres-meta PR #948 (postgrest_version in typegen)

Proposed directions (any one would help)

  1. --schema-only (or similar) for drift checks: emit/compare only public tables/enums, omit __InternalSupabase
  2. Stable cross-mode output: --linked and --local produce comparable files when schema matches
  3. Stable PostgrestVersion in committed output: e.g. omit from default file, or write metadata to a separate generated file
  4. Document official CI drift-check pattern so teams don’t rely on ad-hoc regex normalization

Happy to provide a minimal repro repo or PR to docs if useful.

Environment

  • Supabase CLI: 2.116.0
  • Command: gen types typescript --linked --schema public
  • Schema: unchanged between runs; only PostgrestVersion string changed

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions