fix: correctness fixes across gotrue, postgrest, storage, supabase and supabase_flutter#1445
Merged
Conversation
…age id verifyOTP sent the captcha token under `captchaToken` inside `gotrue_meta_security`, but the server reads `captcha_token`, so the token was silently dropped. resend checked `containsKey(['message_id'])` with a list argument, which is always false, so `ResendResponse.messageId` was never populated.
When `.maybeSingle().count()` matched zero rows and no converter was set, the builder returned `null as T` where `T` is the non-nullable `PostgrestResponse`, throwing a TypeError. It now returns a response with null data and a count of 0, matching the converter branch.
…th normalization A single MultipartFile instance was reused across retry attempts, so a retry re-finalized an already finalized file and threw a StateError instead of retrying. The request factory now builds a fresh MultipartFile per attempt. Binary signed url uploads derived the content type from the full url including the query string, which defeated mime lookup and fell back to application/octet-stream; it now uses the url path. _removeEmptyFolders used JavaScript regex literals that never matched, so it was a no-op; it now uses valid Dart patterns.
…nt headers The headers setter rebuilt the realtime client headers from the client headers only, dropping the apikey entry that is present at construction. It now includes the apikey, matching how the realtime client is built. Also removes a redundant self-spread when merging rest headers before an rpc.
When initialized with a custom accessToken, _restoreSessionCancellableOperation was never assigned, so dispose threw a LateInitializationError. The field is now nullable and cancelled with a null-aware call.
grdsdev
approved these changes
Jun 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A batch of correctness fixes found during a code review sweep. Each fix is in its own per-package commit and ships with a regression test that was verified to fail on the current
mainand pass with the fix.gotrue
verifyOTPsent the captcha token undercaptchaTokeninsidegotrue_meta_security, but the server readscaptcha_token, so the token was silently dropped. Now usescaptcha_tokenlike every other call.resendcheckedcontainsKey(['message_id'])with a list argument (always false), soResendResponse.messageIdwas never populated. Now uses the string key.postgrest
.maybeSingle().count()with zero matching rows and no converter returnednull as TwhereTis the non-nullablePostgrestResponse, throwing aTypeError. Now returns a response with null data andcount: 0.storage_client
MultipartFileinstance was reused across retry attempts, so a retry re-finalized an already finalized file and threw aStateErrorinstead of retrying. The request factory now builds a freshMultipartFileper attempt.?token=query string, defeating mime lookup and falling back toapplication/octet-stream. Now uses the url path._removeEmptyFoldersused JavaScript regex literals (/.../g) that never matched, making it a no-op. Now uses valid Dart patterns so signed url paths are normalized.supabase
headerssetter rebuilt the realtime client headers from the client headers only, dropping theapikeyentry present at construction. Now includes theapikey. Also removes a redundant self-spread when merging rest headers before anrpc.supabase_flutter
accessToken,_restoreSessionCancellableOperationwas never assigned, sodispose()threw aLateInitializationError. The field is now nullable and cancelled with a null-aware call.Test plan
mainand pass with the fix.dart analyzeanddart formatare clean across all changed files.