From 0419494c6d9aeee720f1300d7517c2d6f992bfac Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Wed, 18 Feb 2026 15:04:31 +0200 Subject: [PATCH] docs: add troubleshooting article for UNUSED_EXTERNAL_IMPORT build warning (#42977) ## Description Adds a troubleshooting article for the `UNUSED_EXTERNAL_IMPORT` build warnings that Vite/Rollup/Nuxt users see when bundling apps that use `@supabase/supabase-js`. **File:** `apps/docs/content/troubleshooting/unused-external-import-warning-vite-rollup.mdx` ## What the article covers - What the warning looks like - Why it's a false positive (re-exported external imports not recognised as "used" by Rollup's code-body check) - `onwarn` suppression snippet for Vite/Rollup - `onwarn` suppression snippet for Nuxt ## Related - https://github.com/supabase/supabase-js/issues/2010 - https://github.com/supabase/supabase-js/pull/2122 --------- Co-authored-by: Chris Chinchilla --- .../database/custom-postgres-config.mdx | 6 +- ...ed-external-import-warning-vite-rollup.mdx | 68 +++++++++++++++++++ supa-mdx-lint/Rule001HeadingCase.toml | 2 + supa-mdx-lint/Rule003Spelling.toml | 2 + 4 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 apps/docs/content/troubleshooting/unused-external-import-warning-vite-rollup.mdx diff --git a/apps/docs/content/guides/database/custom-postgres-config.mdx b/apps/docs/content/guides/database/custom-postgres-config.mdx index 2d9d2b6363d..22c1dceae66 100644 --- a/apps/docs/content/guides/database/custom-postgres-config.mdx +++ b/apps/docs/content/guides/database/custom-postgres-config.mdx @@ -55,7 +55,7 @@ Some settings can only be modified by a superuser. Supabase pre-enables the [`su | `log_lock_waits` | Controls whether a log message is produced when a session waits longer than [deadlock_timeout](https://www.postgresql.org/docs/current/runtime-config-locks.html#GUC-DEADLOCK-TIMEOUT) to acquire a lock. | | `log_min_duration_statement` | Causes the duration of each completed statement to be logged if the statement ran for at least the specified amount of time. | | `log_min_messages` | Minimum severity level of messages to log. | -| `log_parameter_max_length` | Sets the maximum length in bytes of data logged for bind parameter values when logging statements. | +| `log_parameter_max_length` | Sets the maximum length in bytes of data logged for bind parameter values when logging statements. | | `log_replication_commands` | Logs all replication commands | | `log_statement` | Controls which SQL statements are logged. Valid values are `none` (off), `ddl`, `mod`, and `all` (all statements). | | `log_temp_files` | Controls logging of temporary file names and sizes. | @@ -65,9 +65,9 @@ Some settings can only be modified by a superuser. Supabase pre-enables the [`su | `pgaudit.*` | Configures the [PGAudit extension](/docs/guides/database/extensions/pgaudit). The `log_parameter` is still restricted to protect secrets | | `pgrst.*` | [`PostgREST` settings](https://docs.postgrest.org/en/stable/references/configuration.html#db-aggregates-enabled) | | `plan_filter.*` | Configures the [pg_plan_filter extension](/docs/guides/database/extensions/pg_plan_filter) | -| `safeupdate.enabled` | Enables the [safeupdate extension](https://github.com/eradman/pg-safeupdate), which requires a `WHERE` clause on `UPDATE` and `DELETE` statements. | +| `safeupdate.enabled` | Enables the [safeupdate extension](https://github.com/eradman/pg-safeupdate), which requires a `WHERE` clause on `UPDATE` and `DELETE` statements. | | `session_replication_role` | Sets the session's behavior for triggers and rewrite rules. | -| `track_functions` | Controls whether function call counts and timing are tracked. Valid values are `none`, `pl` (only procedural-language functions), and `all`. | +| `track_functions` | Controls whether function call counts and timing are tracked. Valid values are `none`, `pl` (only procedural-language functions), and `all`. | | `track_io_timing` | Collects timing statistics for database I/O activity. | | `wal_compression` | This parameter enables compression of WAL using the specified compression method. | diff --git a/apps/docs/content/troubleshooting/unused-external-import-warning-vite-rollup.mdx b/apps/docs/content/troubleshooting/unused-external-import-warning-vite-rollup.mdx new file mode 100644 index 00000000000..e773c531d74 --- /dev/null +++ b/apps/docs/content/troubleshooting/unused-external-import-warning-vite-rollup.mdx @@ -0,0 +1,68 @@ +--- +title = "UNUSED_EXTERNAL_IMPORT build warning with Vite, Rollup, or Nuxt" +topics = [ "platform" ] +keywords = [ "UNUSED_EXTERNAL_IMPORT", "vite", "rollup", "nuxt", "build warning", "false positive", "bundler", "supabase-js" ] +--- + +When bundling an application that uses `@supabase/supabase-js`, you may see warnings like: + +``` +"PostgrestError" is imported from external module "@supabase/postgrest-js" but never used in "...supabase-js/dist/index.mjs". +"FunctionRegion", "FunctionsError", "FunctionsFetchError", "FunctionsHttpError" and "FunctionsRelayError" are imported from external module "@supabase/functions-js" but never used in "...". +``` + +**This is a false positive — your bundle is correct and no code is missing.** + +## Why this happens + +`@supabase/supabase-js` re-exports error types like `PostgrestError` and `FunctionsError` so you can import them directly from `@supabase/supabase-js`. The build tool merges all imports from the same package into a single statement in the output: + +```js +// dist/index.mjs (simplified) +import { PostgrestClient, PostgrestError } from '@supabase/postgrest-js' +// ^ used internally ^ re-exported for you +``` + +Vite/Rollup checks which names from that import are referenced _in the code body_ and flags `PostgrestError` as unused, because it only appears in an `export` statement — not called or assigned. The export itself is the real usage, but this check doesn't account for re-exports. Tree-shaking and bundle size are unaffected. + +## Suppress the warning + +### Vite / Rollup (`vite.config.js` or `rollup.config.js`) + +```js +export default { + build: { + rollupOptions: { + onwarn(warning, warn) { + if (warning.code === 'UNUSED_EXTERNAL_IMPORT' && warning.exporter?.includes('@supabase/')) + return + warn(warning) + }, + }, + }, +} +``` + +### Nuxt (`nuxt.config.ts`) + + + +This issue has been resolved in `@nuxtjs/supabase` version 2.0.4. If you are on that version or later, you do not need to apply this workaround. + + + +```ts +export default defineNuxtConfig({ + vite: { + build: { + rollupOptions: { + onwarn(warning, warn) { + if (warning.code === 'UNUSED_EXTERNAL_IMPORT' && warning.exporter?.includes('@supabase/')) + return + warn(warning) + }, + }, + }, + }, +}) +``` diff --git a/supa-mdx-lint/Rule001HeadingCase.toml b/supa-mdx-lint/Rule001HeadingCase.toml index 1e80c6487e0..dee51c8459d 100644 --- a/supa-mdx-lint/Rule001HeadingCase.toml +++ b/supa-mdx-lint/Rule001HeadingCase.toml @@ -177,6 +177,7 @@ may_uppercase = [ "Quotas", "Query Performance", "React", + "Rollup", "React Email", "React Native", "Read Replicas?", @@ -243,6 +244,7 @@ may_uppercase = [ "Vercel Marketplace", "Visual Studio Code", "VM", + "Vite", "Vue", "Wasm", "Web", diff --git a/supa-mdx-lint/Rule003Spelling.toml b/supa-mdx-lint/Rule003Spelling.toml index 4a9c8f435a8..da1a0cc3c44 100644 --- a/supa-mdx-lint/Rule003Spelling.toml +++ b/supa-mdx-lint/Rule003Spelling.toml @@ -15,6 +15,7 @@ allow_list = [ "\\[#[A-Za-z0-9-]+\\]", "\\$\\$.+?\\$\\$", "\\s\\.[a-z]+", + "\\S+\\.js", "\\S+\\.json", "\\S+\\.toml", "\\S+\\.yaml", @@ -301,6 +302,7 @@ allow_list = [ "RedwoodJS", "Refine", "Roboflow", + "Rollup", "SaaS", "[Ss]avepoint", "SDKs",