parity(realtime): block postgres_changes listener registration after Subscribe() [from supabase-js]
Maintainers usually reply within 1 day
@Tr00d is already working on this.
Since Jul 3, 2026.
Assessment
This issue has not been assessed yet.
Description
SDK Parity: C# implementation needed
A change was made in `supabase-js` that needs to be implemented in this repository for SDK parity.
Reference Implementation (supabase-js)
- PR: feat(realtime): block setting `postgres_changes` event listener after joining
- Merged: 2026-03-30
- Module: realtime
- Type: bug-fix / behavior enforcement
What Changed
The `RealtimeChannel.on()` method was updated to throw an error when attempting to add a `postgres_changes` listener after calling `subscribe()`. Previously, only `presence` listeners were blocked, and only in the `joined` state. The fix:
- Blocks `postgres_changes` listener registration (in addition to `presence`)
- Blocks in both the `joining` and `joined` states (not just `joined`)
- Updates the error message to include the listener type and channel topic
Code Reference
// Before:
if (this.channelAdapter.isJoined() && type === REALTIME_LISTEN_TYPES.PRESENCE) {
throw new Error('cannot add presence callbacks after joining a channel')
}
// After:
const stateCheck = this.channelAdapter.isJoined() || this.channelAdapter.isJoining()
const typeCheck =
type === REALTIME_LISTEN_TYPES.PRESENCE || type === REALTIME_LISTEN_TYPES.POSTGRES_CHANGES
if (stateCheck && typeCheck) {
throw new Error(`cannot add \`${type}\` callbacks for ${this.topic} after \`subscribe()\`.`)
}
Implementation Guidance
Current State in realtime-csharp
The current Register(PostgresChangesOptions) and AddPostgresChangeHandler() methods in RealtimeChannel.cs do not check the channel's subscription state:
public IRealtimeChannel Register(PostgresChangesOptions postgresChangesOptions)
{
PostgresChangesOptions.Add(postgresChangesOptions);
// No guard against calling after Subscribe()
}
public void AddPostgresChangeHandler(ListenType listenType, PostgresChangesHandler postgresChangeHandler)
{
BindPostgresChangesHandler(listenType, postgresChangeHandler);
// No guard against calling after Subscribe()
}
The channel has IsJoining and IsJoined-equivalent properties available via State.
Expected Behavior
When a user calls Register(PostgresChangesOptions) or AddPostgresChangeHandler() on a channel that is already in Joining or Joined state, the SDK should throw an InvalidOperationException with a clear error message.
Key Behaviors to Match
- Throw
InvalidOperationExceptionwhenState == ChannelState.Joining || State == ChannelState.Joined - Error message should identify the operation and channel topic
- Non-postgres/presence operations should not be affected
- Registration before
Subscribe()continues to work normally
Files Likely Affected
Realtime/RealtimeChannel.cs
Acceptance Criteria
- Calling
Register(PostgresChangesOptions)afterSubscribe()throwsInvalidOperationException - Calling
AddPostgresChangeHandler()afterSubscribe()throwsInvalidOperationException - Exception is thrown in both
JoiningandJoinedstates - Non-postgres listeners are not affected by this guard
- Unit tests cover the throwing cases
- No breaking changes to registering postgres_changes before
Subscribe()
Context
- supabase-js PR: https://github.com/supabase/supabase-js/pull/2201
- Parity tracking: This issue was auto-generated by SDK parity analysis
Generated with Claude Code /sync-sdk-parity
- Dominant language
- C#
- Stars
- 700
- Forks
- 105
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 47
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from supabase/supabase-csharp
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
supabase/supabase-csharp#450 ·
Maintainers usually reply within 1 day
-
Difficulty 3/5 1-2 days Newbie friendliness 72/100
supabase/supabase-csharp#474 ·
Maintainers usually reply within 1 day
-
bug(gotrue): FailureReason matches english messages instead of error_codeMay be free again @Tr00d claimed this 28 days ago, and no pull request is open. Open
supabase/supabase-csharp#409 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
OAuth State Error for social providers since Supabase.Gotrue v6.1.0May be free again @Tr00d claimed this 39 days ago, and no pull request is open. Openbug
supabase/supabase-csharp#377 · 3 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
Postgres Changes filters are validated as anon because SetAuth is applied after channel joinMay be free again @Tr00d claimed this 52 days ago, and no pull request is open. Openarea: postgrest bug
supabase/supabase-csharp#345 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
All issues in supabase/supabase-csharp
Similar issues
-
area/navigationview 🧭 difficulty/starter 🚀 good first issue kind/bug platform/all project/navigation-lifecycle 🧬 triage/untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
unoplatform/uno#24925 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
DamianEdwards/ghcp-spend-tray#39 ·
Maintainers usually reply within 1 day
-
copilot documentation
Difficulty 1/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 2 days
-
[Rust][Flaky Test] multiple_deadlines_fire_in_order asserts a wall-clock gap instead of firing orderOpenCI/CD ⚒️ Flaky-tests 🐦
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
valkey-io/valkey-glide#7255 ·
Maintainers usually reply within 3 days
-
bug good first issue
Difficulty 1/5 Under an hour Newbie friendliness 92/100
unoplatform/Uno.Core#99 ·