chore: enable avoid-passing-async-when-sync-expected lint#1455
Merged
Conversation
grdsdev
approved these changes
Jun 22, 2026
Enable the DCM avoid-passing-async-when-sync-expected rule so that async callbacks are not passed where a synchronous one is expected, which would discard the returned future and silently lose its errors. Resolve all violations by making the callbacks synchronous and either wrapping the genuinely fire-and-forget work in unawaited() or extracting it into a dedicated method.
Use the mockServer.first + held-future pattern already used by the httpSend tests instead of the Completer plus unawaited(...then...) dance. The 'via ws conn when subscribed' test previously did its assertions inside the subscribe callback, which never fired against the raw mock server, so it asserted nothing. It now upgrades the websocket, replies to the channel join, and verifies the broadcast is actually pushed over the socket.
The extracted join handler only indexes the response by key, so Map expresses the contract without resorting to dynamic. Map rather than Map<String, dynamic> because the test helpers trigger replies with loosely typed maps.
… dynamic>
Typing Push.trigger's response parameter fixes the source of the loosely
typed reply maps (the trigger('ok', {}) literals now infer
Map<String, dynamic>), so _handleJoinOk can take a typed map instead of a
raw one.
spydon
force-pushed
the
chore/avoid-passing-async-when-sync-expected
branch
from
June 22, 2026 17:20
c5f8178 to
1115971
Compare
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.
What
Enables the DCM rule
avoid-passing-async-when-sync-expected(removing it from the ratchet list insupabase_lints) and resolves the 13 resulting violations.Why
When an
asynccallback is passed where a synchronous one is expected, the returnedFutureis discarded, so if it throws the error is silently lost. This is the same class of problem as theunawaited_futures/discarded_futureslints in #1454, just at call sites that take a callback. Enabling it closes the remaining async-safety gap.How
Each of the 13 sites was made synchronous, and the inner async work was either wrapped in
unawaited(...)(genuine fire-and-forget) or extracted into a dedicated method, preserving existing behavior and error handling. Highlights:realtime_channel.dart: extracted thejoinPush.receive('ok', ...)body into_handleJoinOk(...)(theInvalidJWTTokensetAuth handling is preserved verbatim).realtime_client.dart: extracted reconnect into_reconnect(), heartbeat timer callback made sync withunawaited(sendHeartbeat()).supabase_client.dart:onAuthStateChangeSynclistener made sync withunawaited(_handleTokenChanged(...)).supabase_stream_builder.dart:onDone: controller.close→onDone: () => unawaited(controller.close())in the asyncMap/asyncExpand reimplementations.No public API signatures were changed.
Verification
dcm analyze: 0avoid-passing-async-when-sync-expectedacross all packages.dart analyze: clean, no newunawaited_futures/discarded_futures.