[DX-1211] Add strictMode client option and granted-mode checks on subscribe and presence.get#505
Merged
Merged
Conversation
… presence.get New spec points TO3r (strictMode ClientOptions attribute), RTL7i (RealtimeChannel#subscribe checks granted modes for SUBSCRIBE) and RTP11f (RealtimePresence#get checks granted modes for PRESENCE_SUBSCRIBE), so that operations whose effect depends on a channel mode the server did not grant fail with an ErrorInfo (strictMode true) or log a warning while preserving their legacy silent result (strictMode false, the default). Reference implementation: ably/ably-js#2236. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
umair-ably
added a commit
to ably/ably-js
that referenced
this pull request
Jul 14, 2026
…roposed spec points Spec point IDs RTL7i1/RTL7i2 and RTP11f1/RTP11f2 are proposed in ably/specification#505 and are provisional until that PR merges. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AndyTWF
reviewed
Jul 15, 2026
| | useBinaryProtocol: Bool default true ||| TO3f | When `true`, the more efficient MsgPack binary encoding is used. When `false`, JSON text encoding is used. The default is `true`. | | ||
| | transportParams: [String: Stringifiable]? ||| RTC1f | A set of key-value pairs that can be used to pass in arbitrary connection parameters, such as [`heartbeatInterval`](https://ably.com/docs/realtime/connection#heartbeats) or [`remainPresentFor`](https://ably.com/docs/realtime/presence#unstable-connections). | | ||
| | addRequestIds: Bool default false ||| TO3p | When `true`, every REST request to Ably should include a random string in the `request_id` query string parameter. The random string should be a url-safe base64-encoding sequence of at least 9 bytes, obtained from a source of randomness. This request ID must remain the same if a request is retried to a fallback host. Any log messages associated with the request should include the request ID. If the request fails, the request ID must be included in the [`ErrorInfo`]{@link ErrorInfo} returned to the user. The default is `false`. | | ||
| | strictMode: Bool default false ||| TO3r | When `true`, operations that would otherwise fail silently, such as those gated on a granted channel mode, fail with an [`ErrorInfo`]{@link ErrorInfo} describing the cause. When `false`, the same operations log a warning and return their legacy result. The default is `false`. A future major version will change the default to `true`. | |
Contributor
There was a problem hiding this comment.
Suggested change
| | strictMode: Bool default false ||| TO3r | When `true`, operations that would otherwise fail silently, such as those gated on a granted channel mode, fail with an [`ErrorInfo`]{@link ErrorInfo} describing the cause. When `false`, the same operations log a warning and return their legacy result. The default is `false`. A future major version will change the default to `true`. | | |
| | strictMode: Bool default false ||| TO3r | When `true`, operations that would otherwise fail silently, such as those gated on a granted channel mode, will instead throw an [`ErrorInfo`]{@link ErrorInfo} describing the cause. When `false`, the same operations log a warning and return their legacy result. The default is `false`. A future major version will change the default to `true`. | |
| - `(TO3o)` `plugins` `Dict<PluginType:Plugin>` A map between a `PluginType` and a `Plugin` object. The client library might downcast a `Plugin` to particular plugin type. | ||
| - `(TO3p)` `addRequestIds` boolean - defaults to false. If true, `RSC7c` applies | ||
| - `(TO3q)` `transportParams` \[String: Stringifiable\]? - defaults to null. Described in [RTC1f](#RTC1f) | ||
| - `(TO3r)` `strictMode` boolean - defaults to `false`. Controls the behaviour of certain operations that, for historical reasons, complete successfully even though the client is in a state in which the operation cannot have its intended effect, such as operations gated on a granted channel mode (see [`RTL7i`](#RTL7i), [`RTP11f`](#RTP11f)). It is intended that a future major version of the specification will change the default to `true` |
Contributor
There was a problem hiding this comment.
Perhaps a minor wording consideration - would we make StrictMode true, or would we just fix the underlying issues in a major release?
Contributor
Author
There was a problem hiding this comment.
good spot, reworded to highlight the strictMode behaviour becomes the default
…on surviving the next major Apply Andy's suggestion that strictMode operations "will instead throw" an ErrorInfo, and say a future major adopts the strict behaviour by default rather than that the default flips: whether v-next flips the strictMode default or removes the option and fixes the underlying behaviour unconditionally is not yet decided. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
36b13e3 to
36e1562
Compare
umair-ably
added a commit
to ably/ably-js
that referenced
this pull request
Jul 15, 2026
…ictMode default flips Align with the TO3r wording agreed on ably/specification#505: a future major adopts the strict behaviour by default, whether by changing the strictMode default or by making the behaviour unconditional and retiring the option. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AndyTWF
approved these changes
Jul 15, 2026
umair-ably
added a commit
to ably/ably-js
that referenced
this pull request
Jul 15, 2026
…ictMode default flips A future major makes the strict behaviour unconditional; don't imply the strictMode option survives with a flipped default. Aligns with the TO3r wording agreed on ably/specification#505. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Author's Note
Extends spec to include new strictMode behaviour as implemented in ably/ably-js#2236. Spec changes highlight whether the error is thrown or logged for previously silent subscribe and presence errors caused by channel mode mismatches.
What: Specifies the behaviour when a client performs an operation whose effect depends on a channel mode the server did not grant:
RealtimeChannel#subscribewithoutSUBSCRIBE(newRTL7i) andRealtimePresence#getwithoutPRESENCE_SUBSCRIBE(newRTP11f). Adds astrictModeclient option (TO3r) that selects between failing the operation (true) and the legacy silent result plus anERROR-level log (false, the default), allowing SDKs to ship the fix additively before a future major version flips the default.Why: Today these calls fail silently —
presence.get()resolves with[]andsubscribe()registers a listener that never fires. This is a significant DX trap for both humans and coding agents (see ably/ably-js#2236 for experiments quantifying agent failure rates: 50% unrecoverable → 0% with strict failures). The checks use the granted mode set (RTL4m), not the requested modes, so they also catch the case where a capability restriction caused the server to silently drop a requested mode.Error codes: 90009 (
subscribe_mode_not_enabled) and 91008 (presence_subscribe_mode_not_enabled) are already registered in ably-common.Deliberately out of scope: presence enter/update/leave without the
presencemode (the server NACKs those, so they are not silent); theErrorInforemediation/hint field ably-js attaches to these errors (naming under separate discussion); and the annotations mode check (RTAN4e), where ably-js already fails the call today — deviating from other SDKs, which log per the current spec text — sostrictModegating is not necessary there to preserve existing behaviour.Reference implementation: ably/ably-js#2236.
🤖 Generated with Claude Code