parity(realtime): block postgres_changes listener registration after Subscribe() [from supabase-js]
@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
- 701
- Forks
- 106
- Avg merge
- 16h 35m
- Merged PRs (30d)
- 45
Contributor 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 82/100
supabase/supabase-csharp#440 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
supabase/supabase-csharp#437 ·
-
Difficulty 4/5 3-5 days Newbie friendliness 52/100
supabase/supabase-csharp#427 ·
-
supabase/supabase-csharp#409 · 1 comment · 1 assignee ·
-
area: realtime bug parity
supabase/supabase-csharp#393 · 1 assignee ·
All issues in supabase/supabase-csharp
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
:watch: Not Triaged 11.0 fundamentals/subsvc
Difficulty 2/5 1-3 hours Newbie friendliness 92/100
dotnet/AspNetCore.Docs#37699 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SubtitleEdit/subtitleedit#15108 · 1 comment ·
-
area/docs-content Bug pulumi/docs
Difficulty 1/5 1-3 hours Newbie friendliness 94/100
-
agentic-workflows untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 76/100