fix(studio): show compute waitlist notice when project is not enrolled (#51224)

Resolves FUNC-941

## What

When a project isn't enrolled in Compute, show a short notice with a
link to the waitlist (https://supabase.com/compute) instead of a generic
error.

## Why

The compute API returns its 404 as `{ "error": { "code", "message" } }`.
`handleError` only reads a top-level `message`, so it dropped the status
code, `isComputeUnavailable` never matched, and users saw "API error
happened while trying to communicate with the server." The query now
checks `response.status === 404` directly.

## Testing

- [ ] Project not enrolled in Compute: the waitlist notice shows
- [ ] Enrolled project: the instance list loads as before
This commit is contained in:
Ali Waseem authored and GitHub committed 2026-10-03 20:34:14 +00:00
1 parent 4ab54b9359
commit 7353782724
3 files changed
+43 -10

No files matched your search

+5 -2
View File
@@ -4,7 +4,7 @@ import { computeRefetchInterval, parseComputeInstance } from './compute.utils'
import { computeKeys } from './keys'
import { get, handleError } from '@/data/fetchers'
import { IS_PLATFORM } from '@/lib/constants'
import type { ResponseError } from '@/types'
import { ResponseError } from '@/types'
export type ComputeVariables = { projectRef?: string }
export type ComputeError = ResponseError
@@ -12,11 +12,14 @@ export type ComputeError = ResponseError
async function getComputeInstances({ projectRef }: ComputeVariables, signal?: AbortSignal) {
if (!projectRef) throw new Error('projectRef is required')
const { data, error } = await get('/v2/projects/{ref}/compute', {
const { data, error, response } = await get('/v2/projects/{ref}/compute', {
params: { path: { ref: projectRef } },
signal,
})
if (response.status === 404) {
throw new ResponseError('Compute is not available for this project', 404)
}
if (error) return handleError(error)
return data.data.map((instance) => parseComputeInstance(instance))
}
@@ -1,6 +1,6 @@
import { useQuery } from '@tanstack/react-query'
import { useParams } from 'common'
import { RefreshCw } from 'lucide-react'
import { ExternalLink, RefreshCw } from 'lucide-react'
import { useState } from 'react'
import { Button } from 'ui'
import { Admonition } from 'ui-patterns/Admonition'
@@ -79,8 +79,20 @@ const ComputePage: NextPageWithLayout = () => {
{isNotEnrolled && (
<Admonition
type="default"
title={`${PRODUCT_NAME} is not enabled for this project`}
description={`${PRODUCT_NAME} is in Private Alpha. Contact support to have this project added to the alpha.`}
layout="horizontal"
title={`You don't have access to ${PRODUCT_NAME} yet`}
description="Join the waitlist to get early access."
actions={
<Button asChild icon={<ExternalLink />}>
<a
href="https://supabase.com/compute"
target="_blank"
rel="noopener noreferrer"
>
Join waitlist
</a>
</Button>
}
/>
)}
{isMissingPermission && (
@@ -1,14 +1,15 @@
import { QueryClient } from '@tanstack/react-query'
import { fireEvent, screen } from '@testing-library/react'
import type { components } from 'api-types'
import { HttpResponse } from 'msw'
import { http, HttpResponse } from 'msw'
import { beforeEach, describe, expect, it } from 'vitest'
import { computeQueryOptions } from '@/data/compute/compute-query'
import { API_URL } from '@/lib/constants'
import { PRODUCT_NAME } from '@/lib/constants/compute'
import ComputePage from '@/pages/project/[ref]/compute/index'
import { customRender } from '@/tests/lib/custom-render'
import { addAPIMock, type APIErrorBody } from '@/tests/lib/msw'
import { addAPIMock, mswServer, type APIErrorBody } from '@/tests/lib/msw'
import { routerMock } from '@/tests/lib/route-mock'
type ListComputeInstancesResponse = components['schemas']['V2ListComputeInstancesResponse_Output']
@@ -101,12 +102,29 @@ describe('/project/[ref]/compute', () => {
expect(await screen.findByRole('link', { name: 'embed' })).toBeVisible()
})
it('explains that a project outside the alpha is not enrolled', async () => {
mockComputeInstancesListFailure(404)
it('points a project outside the alpha to the waitlist', async () => {
mswServer.use(
http.get(`${API_URL}/v2/projects/:ref/compute`, () =>
HttpResponse.json(
{
error: {
code: 'not_found.compute.not_enabled',
message: 'Compute is not available for this project',
},
},
{ status: 404 }
)
)
)
await renderComputePage()
expect(screen.getByText(`${PRODUCT_NAME} is not enabled for this project`)).toBeVisible()
expect(screen.getByText(`You don't have access to ${PRODUCT_NAME} yet`)).toBeVisible()
expect(screen.getByRole('link', { name: 'Join waitlist' })).toHaveAttribute(
'href',
'https://supabase.com/compute'
)
expect(screen.queryByText('Failed to retrieve compute instances')).not.toBeInTheDocument()
expect(screen.queryByRole('table')).not.toBeInTheDocument()
})