This one likely needs Supabase support to look at the project from their side. The browser checks you already tried are reasonable, but `Failed to retrieve pause status: Error: No backups found` does not look like a client-side/cache issue. It usually points to the resume flow not being able to find the backup/pause metadata it expects for that project. For paused projects, the dashboard needs to confirm the project’s paused state and locate the backing restore data before it can bring the database back online. If that lookup returns `No backups found`, there probably is not anything you can fix locally from the dashboard, CLI, or a different browser session. What I would do next: - Open a Supabase support ticket from the dashboard and include the project ref: `dbsdrrcjqibvxosyuhhj` - Include the exact error text: ```text Failed to retrieve pause status Error: No backups found ``` - Mention that you already tried refresh, incognito, another browser, and waiting/retrying. - Include the screenshot and the approximate time/date when you attempted to resume the project. - If the project is on a paid org, make sure the ticket is opened from the same org/account that owns the project. GitHub Discussions can help identify whether others have seen the same symptom, but this specific failure is tied to Supabase’s internal project/backup state. A Supabase team member will likely need to check whether the project’s pause record or backup metadata is missing, delayed, or in a bad state, and then manually correct or resume it. One small thing worth checking while waiting: confirm you are logged into the correct Supabase account/org and that the project still appears under the expected organization in the dashboard. If it does, and the resume button consistently hits the same `No backups found` error, support intervention is the right path. --- If my answer solved your problem, you can click **answered the question**. I'm really here to help, and along the way I'm also collecting Galaxy Brain badges haha 😆
This looks like the previous failed storage request is leaving something open in the Bun runtime/client connection state, rather than RLS itself “blocking” the next test. A policy-denied upload should come back as a normal Storage API error, usually `403`/`42501`-style depending on where it fails, and the next request should still be able to proceed. The first thing worth isolating is whether the hang is tied to reusing the same `SupabaseClient` / auth session / HTTP connection after the denied upload. Since this is in Bun, I would make the denied-upload test fully self-contained and force a fresh client for the next test: ```ts afterEach(async () => { await supabase.auth.signOut() // Give Bun a chance to close pending fetch/body work between tests. await new Promise((resolve) => setTimeout(resolve, 0)) }) ``` Also make sure the denied upload is not accidentally leaving a promise unobserved. The denied request should be awaited and asserted directly: ```ts const { data, error } = await supabase.storage .from('user_profiles') .upload(`${otherUserId}/${imageName}`, imageContent) expect(data).toBeNull() expect(error).not.toBeNull() ``` If the next upload still hangs, try creating a completely new Supabase client after the denied upload rather than only signing out: ```ts afterEach(async () => { await supabase.auth.signOut() supabase = undefined as any }) ``` And in each test: ```ts beforeEach(() => { supabase = createSupabaseClient() }) ``` One important thing in this test setup: avoid sharing the same storage object path across tests. If two tests generate `Date.now()` names close together, or if a failed test leaves an object behind, later uploads can behave differently depending on `upsert`, ownership policies, and object metadata. I’d include the test name/user id plus a random suffix: ```ts const imageName = `test-image-${crypto.randomUUID()}.jpg` ``` For the RLS test specifically, I would also verify that the policy is denying at the `storage.objects` layer and not timing out while talking to rustFS. A quick way to separate those is to check the Storage service logs while the test hangs. If the denied request logs a completed `403` but the following upload never reaches storage-api, that points more toward Bun/client connection reuse. If the following upload reaches storage-api and stalls while writing to rustFS, that points at the storage backend path instead. A useful workaround to confirm the connection-reuse theory is to inject a fetch implementation that does not reuse state between requests, or at least add a timeout wrapper around the storage call so the test fails with context instead of hanging forever: ```ts async function withTimeout<T>(promise: Promise<T>, ms = 10_000): Promise<T> { const timeout = new Promise<never>((_, reject) => setTimeout(() => reject(new Error(`Timed out after ${ms}ms`)), ms) ) return Promise.race([promise, timeout]) } const { data, error } = await withTimeout( supabase.storage .from('user_profiles') .upload(`${userId}/${imageName}`, imageContent), ) ``` The snippet is cut off at `signI`, so the exact denied upload path and the later hanging test are missing. The most useful extra details would be: - the rest of the denied-upload test and the test that hangs; - the exact RLS policies on `storage.objects`; - whether the hang happens with Node/Vitest or only with `bun:test`; - storage-api logs for the denied request and the subsequent hanging upload; - whether the same behavior occurs with the default S3/minio-compatible backend instead of rustFS. --- If my answer solved your problem, you can click **answered the question**. I'm really here to help, and along the way I'm also collecting Galaxy Brain badges haha 😆
The issue templates aren’t in `supabase/supabase` itself. That repo’s `.github/` directory currently has things like `workflows`, `CODEOWNERS`, and `pull_request_template.md`, but no local `ISSUE_TEMPLATE` directory. ([github.com](https://github.com/supabase/supabase/tree/master/.github)) They live in the org-level shared `.github` repository: ```text supabase/.github/.github/ISSUE_TEMPLATE/1.Bug_report.md supabase/.github/.github/ISSUE_TEMPLATE/2.Improve_docs.md supabase/.github/.github/ISSUE_TEMPLATE/3.Create_a_chore.md supabase/.github/.github/ISSUE_TEMPLATE/config.yml ``` Those are the three templates you mentioned: `Bug report`, `Improve documentation`, and `Create a chore`. The `config.yml` file controls the template chooser behavior, including contact links and whether blank issues are allowed. ([github.com](https://github.com/supabase/.github/tree/main/.github/ISSUE_TEMPLATE)) GitHub supports this pattern through default community health files: an organization can define shared issue templates in its `.github` repo, and repositories without their own local templates can use those defaults. ([docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/about-issue-and-pull-request-templates?ref=froilan-irizarry-rivera)) For a refactor, the PR should target `supabase/.github`, not `supabase/supabase`. I’d keep the numbered filenames unless you also want to change the order in the issue template chooser. If the goal is faster filling, worth checking whether maintainers would prefer keeping these as Markdown templates or moving them to GitHub issue forms (`.yml`) for fields, dropdowns, and required inputs. --- If my answer solved your problem, you can click **answered the question**. I'm really here to help, and along the way I'm also collecting Galaxy Brain badges haha 😆
Thanks for the detailed write-up - this does look like a real client-side robustness issue, not just a docs/UX problem around short JWT expiries. The proposed offset approach makes sense to me. If the client can derive “server now” from a freshly issued token or response metadata, then expiry checks should consistently compare against that adjusted time instead of raw `Date.now()`. That would prevent the bad loop where every newly refreshed session is immediately treated as expired on machines with clocks far in the future. A few implementation details seem important: - The offset should be recomputed on every sign-in and refresh, not treated as a permanent setting. - It should be applied consistently anywhere auth-js evaluates expiry: `__loadSession()`, `_autoRefreshTokenTick()`, helper methods like `expiresAt()`, and any related refresh scheduling. - It should handle clock correction gracefully. If the user fixes their OS clock while the app is running, the next successful auth response should bring the offset back toward zero. - It may be worth bounding or sanity-checking the offset so a malformed token or unexpected response does not poison session handling. Using `iat` is probably good enough for this because it comes from the server-issued JWT and matches the server’s view of issuance time. The response `Date` header would also be attractive if it is reliably available in the environments auth-js supports, but `iat` has the advantage of already being part of the session payload. A configurable time source could still be useful for tests or advanced integrations, but I would not want that to be the only fix. The failure mode affects normal users who will not know they need to configure anything, so automatic skew compensation seems like the better default behavior. One subtle point: a plain `clockTolerance` option helps with small drift, but it does not really solve the production case you described where the device is off by minutes or hours. An offset-derived “effective now” seems more solid than increasing the expiry margin globally. This feels like a reasonable change to auth-js as long as it is centralized and covered with regression tests for clocks ahead/behind the server. A good test case would be: local clock ahead by more than the JWT lifetime, sign in succeeds, `getSession()` does not immediately refresh-loop, and the auto-refresh timer schedules from adjusted server time rather than local wall-clock time. --- If my answer solved your problem, you can click **answered the question**. I'm really here to help, and along the way I'm also collecting Galaxy Brain badges haha 😆
Thanks for laying this out. The use case makes sense: log drains are most useful when they can preserve the context that downstream tools use for correlation, and a fixed payload makes that hard for systems like Sentry that expect trace/session fields in specific places. The main feature request here seems to be configurable enrichment/mapping before delivery, not just “send logs somewhere”. For example: - map an existing request/session/header value into a custom field - rename or reshape fields to match the destination schema - include/exclude specific fields - add static fields per drain - potentially support lightweight templating for the outgoing payload For the Sentry case specifically, being able to promote a session or trace identifier into the drained log payload would be much better than relying on a header that only appears as metadata and then manually querying around it later. Arbitrary transforms may be harder to support safely because log drains need to stay reliable, predictable, and low-latency, but a declarative mapping layer could cover a lot of practical cases without turning drains into a full processing pipeline. This would also help beyond Sentry. Most log platforms have their own preferred shape for severity, timestamp, service name, trace id, environment, and metadata, so some amount of payload customization would make drains easier to integrate generally. This sounds worth tracking as a feature request for log drain configuration: field mapping/enrichment first, with more advanced transforms considered separately if there’s enough demand. --- If my answer solved your problem, you can click **answered the question**. I'm really here to help, and along the way I'm also collecting Galaxy Brain badges haha 😆
The screenshots narrow this down pretty well: the second one shows the same session seeing `visible_chunks = 3` for `authenticated` with the expected `jwt_sub`, while the SQL RPC wrapper returns `function_rows = 0`. The catalog screenshot also rules out the common “wrong overload / SECURITY DEFINER / SET search_path” explanation: there’s one `match_kb_chunks(vector,integer)`, `security_definer = false`, owner `postgres`, and `set_clauses = NULL`. This does **not** look like a PostgREST pooler or prepared-statement cache issue. Since it reproduces directly in the SQL editor in the same transaction after `set local role authenticated`, PostgREST and the pooler are mostly out of the path. `notify pgrst, 'reload schema'` would only affect PostgREST’s schema cache anyway; it would not change behavior for a direct SQL call. The thing I’d check hardest is SQL-function name binding, not pgvector. In `LANGUAGE sql` functions, unqualified argument names can lose to column names inside the function body. That can make a function that looks semantically identical behave differently from the manually inlined query, especially if the function has args like `embedding`, `match_count`, `query_embedding`, `source_document_id`, etc. A `plpgsql` version may avoid the same binding path, which matches what you’re seeing. Try recreating the SQL function using positional args only, fully qualified table aliases, and an explicit search path/operator schema if needed: ```sql create or replace function public.match_kb_chunks( query_embedding extensions.vector, match_count integer ) returns table ( -- your return columns here ) language sql stable security invoker set search_path = public, extensions as $$ select -- columns here from public.knowledge_base_documents kbd where kbd.source_document_id is not null and kbd.embedding is not null -- use $1 and $2, not argument names -- example: -- and (kbd.embedding <=> $1) < some_threshold order by kbd.embedding <=> $1 limit $2 $$; ``` If that fixes it, the root cause was almost certainly identifier resolution inside the SQL function body. If it does not, the next useful comparison is: ```sql explain (analyze, verbose, settings) select * from public.match_kb_chunks( ( select ('[' || string_agg('0.01', ',') || ']')::extensions.vector(1536) from generate_series(1, 1536) ), 8 ); ``` and the same `EXPLAIN` for the raw inlined `SELECT`. The `VERBOSE` output should show whether the function body is being inlined, which filters are actually applied, and whether the vector expression is the same expression you think it is. --- If my answer solved your problem, you can click **answered the question**. I'm really here to help, and along the way I'm also collecting Galaxy Brain badges haha 😆
The project ref is enough for Supabase support to locate it, but the owning org / membership state can’t be confirmed from a public GitHub Discussion. If the support flow requires an org and your account currently has none, create a temporary/free org just to get access to the support form, then open an account/project ownership ticket with the project ref `vfyarawrpvcioryisicr`. Include the following in the ticket: project ref, project URL, GitHub username, GitHub email, approximate creation date, Lovable involvement, and screenshots of the dashboard access error + CLI error. Don’t post service role keys or database credentials publicly. One thing worth checking locally before filing: make sure the CLI is not using an old access token from a different Supabase account. ```bash npx supabase logout npx supabase login npx supabase projects list ``` Also, if Lovable provisioned or managed the Supabase project at any point, contact Lovable support too. Supabase project ownership is tied to a Supabase organization, not to the GitHub repo or the presence of the project ref in `.env` / `config.toml`.
Thanks for the suggestion - this makes sense. The GitHub integration currently creates preview branches without exposing the CLI’s `--with-data` behavior, so adding a UI toggle for “include data” would be the right shape for this. One consideration is that data cloning can have cost/performance/security implications depending on project size and contents, so the setting would likely need to be explicit and probably disabled by default. For now, the workaround is to create the branch via the CLI using: ```bash supabase branches create <branch-name> --with-data ``` Leaving this open as a feature request for the GitHub integration.