From ae8c1fc2d8ca4885a722b2ede44987e0e90b775c Mon Sep 17 00:00:00 2001 From: pieh Date: Tue, 28 Apr 2026 10:14:40 +0200 Subject: [PATCH 1/5] fix: don't error remote database status if database was not enabled yet to provide more meaningful output --- src/commands/database/db-status.ts | 11 ++++++++-- .../unit/commands/database/db-status.test.ts | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/commands/database/db-status.ts b/src/commands/database/db-status.ts index 346024c3384..fe794f85b42 100644 --- a/src/commands/database/db-status.ts +++ b/src/commands/database/db-status.ts @@ -410,9 +410,16 @@ export const statusDb = async (options: DatabaseStatusOptions, command: BaseComm throw new Error(`You must be logged in with ${netlifyCommand()} login to target a remote branch.`) } - connectionString = await fetchBranchConnectionString({ siteId, accessToken, basePath }, branch) - fetchApplied = remoteAppliedMigrations({ siteId, accessToken, basePath, branch }) branchLabel = branch + if (enabled) { + connectionString = await fetchBranchConnectionString({ siteId, accessToken, basePath }, branch) + fetchApplied = remoteAppliedMigrations({ siteId, accessToken, basePath, branch }) + } else { + // When the database isn't enabled, skip the remote fetch — the branch endpoint would 404 with + // a non-actionable error. The pending-migrations hint below directs users to install + // @netlify/database and deploy, which is the actionable next step. + fetchApplied = () => Promise.resolve([]) + } } else { isLocal = true branchLabel = 'local' diff --git a/tests/unit/commands/database/db-status.test.ts b/tests/unit/commands/database/db-status.test.ts index 8dc31ae79d3..18b5ad95f29 100644 --- a/tests/unit/commands/database/db-status.test.ts +++ b/tests/unit/commands/database/db-status.test.ts @@ -767,6 +767,26 @@ describe('statusDb', () => { expect(jsonMessages[0]).toMatchObject({ target: 'feature-x' }) }) + test('does not fetch branch connection string or remote applied migrations when database is not enabled', async () => { + setupFetchRouter({ siteDatabase: null }) + + await expect(statusDb({ branch: 'feature-x' }, createMockCommand())).resolves.not.toThrow() + + const fetchedUrls = mockFetch.mock.calls.map((c) => { + const u = c[0] as URL | string + return typeof u === 'string' ? u : u.toString() + }) + expect(fetchedUrls.some((u) => u.includes('/database/branch/'))).toBe(false) + expect(fetchedUrls.some((u) => u.includes('/database/migrations'))).toBe(false) + expect(mockConnectToDatabase).not.toHaveBeenCalled() + + const output = logMessages.join('\n') + expect(output).toContain('Netlify Database is not enabled for this project') + expect(output).toContain('Applied migrations (0)') + expect(output).toContain('Pending migrations (0)') + expect(output).not.toContain('Connected to database branch') + }) + test('throws a helpful error when the branch endpoint 404s', async () => { setupFetchRouter({ siteDatabase: { connection_string: PROD_CONN } }) From 4ea63a0ea1d7b008b725c067439f900e31b04d07 Mon Sep 17 00:00:00 2001 From: pieh Date: Tue, 28 Apr 2026 10:44:05 +0200 Subject: [PATCH 2/5] test: adjust not throwing assertion --- tests/unit/commands/database/db-status.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/commands/database/db-status.test.ts b/tests/unit/commands/database/db-status.test.ts index 18b5ad95f29..2c6afed971e 100644 --- a/tests/unit/commands/database/db-status.test.ts +++ b/tests/unit/commands/database/db-status.test.ts @@ -770,7 +770,7 @@ describe('statusDb', () => { test('does not fetch branch connection string or remote applied migrations when database is not enabled', async () => { setupFetchRouter({ siteDatabase: null }) - await expect(statusDb({ branch: 'feature-x' }, createMockCommand())).resolves.not.toThrow() + await expect(statusDb({ branch: 'feature-x' }, createMockCommand())).resolves.toBeUndefined() const fetchedUrls = mockFetch.mock.calls.map((c) => { const u = c[0] as URL | string From 4e6fa3e4316c77e0ee0dae638d790f290e691ac9 Mon Sep 17 00:00:00 2001 From: pieh Date: Wed, 29 Apr 2026 20:01:24 +0200 Subject: [PATCH 3/5] fix: check if site has database instead of checking computed enabled database-proxy might be setting connection string and provision on demand, tricking into thinking that database is already provisioned --- src/commands/database/db-status.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/database/db-status.ts b/src/commands/database/db-status.ts index fe794f85b42..49f550e89cf 100644 --- a/src/commands/database/db-status.ts +++ b/src/commands/database/db-status.ts @@ -411,11 +411,11 @@ export const statusDb = async (options: DatabaseStatusOptions, command: BaseComm } branchLabel = branch - if (enabled) { + if (siteHasDatabase) { connectionString = await fetchBranchConnectionString({ siteId, accessToken, basePath }, branch) fetchApplied = remoteAppliedMigrations({ siteId, accessToken, basePath, branch }) } else { - // When the database isn't enabled, skip the remote fetch — the branch endpoint would 404 with + // When site does not have database, skip the remote fetch — the branch endpoint would 404 with // a non-actionable error. The pending-migrations hint below directs users to install // @netlify/database and deploy, which is the actionable next step. fetchApplied = () => Promise.resolve([]) From 6b0ffd029694bdcf0a8463f2965fd0d7d197f767 Mon Sep 17 00:00:00 2001 From: pieh Date: Wed, 29 Apr 2026 20:37:58 +0200 Subject: [PATCH 4/5] skip self-explaining comment --- src/commands/database/db-status.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/commands/database/db-status.ts b/src/commands/database/db-status.ts index 49f550e89cf..a21a01ec49c 100644 --- a/src/commands/database/db-status.ts +++ b/src/commands/database/db-status.ts @@ -415,9 +415,6 @@ export const statusDb = async (options: DatabaseStatusOptions, command: BaseComm connectionString = await fetchBranchConnectionString({ siteId, accessToken, basePath }, branch) fetchApplied = remoteAppliedMigrations({ siteId, accessToken, basePath, branch }) } else { - // When site does not have database, skip the remote fetch — the branch endpoint would 404 with - // a non-actionable error. The pending-migrations hint below directs users to install - // @netlify/database and deploy, which is the actionable next step. fetchApplied = () => Promise.resolve([]) } } else { From bf68be15f317e2bafe4ef4cbd98da76f6fbb3927 Mon Sep 17 00:00:00 2001 From: pieh Date: Tue, 5 May 2026 19:14:41 +0200 Subject: [PATCH 5/5] fix: don't throw when remote migrations response is null --- src/commands/database/util/applied-migrations.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/commands/database/util/applied-migrations.ts b/src/commands/database/util/applied-migrations.ts index 1fecaf34634..42cf733a980 100644 --- a/src/commands/database/util/applied-migrations.ts +++ b/src/commands/database/util/applied-migrations.ts @@ -37,7 +37,7 @@ interface RemoteMigration { } interface ListMigrationsResponse { - migrations: RemoteMigration[] + migrations: RemoteMigration[] | null } export const remoteAppliedMigrations = @@ -59,7 +59,9 @@ export const remoteAppliedMigrations = } const data = (await response.json()) as ListMigrationsResponse - return data.migrations.filter((m) => m.applied).map((m) => ({ version: m.version, name: m.name, path: m.path })) + return ( + data.migrations?.filter((m) => m.applied).map((m) => ({ version: m.version, name: m.name, path: m.path })) ?? [] + ) } interface LocalOptions {