Skip to content

WS: generic subscribe() silently drops unknown params keys #195

Closed

Description

@TexasCoding

Summary

Subscription.to_subscribe_params() only forwards keys listed in the hardcoded _SUBSCRIBE_FORWARD_KEYS tuple. Any other key the user passes via the public KalshiWebSocket.subscribe(channel, params={...}) escape hatch is silently dropped before the wire command is sent.

Failure modes:

  • params={'tickers': [...]} (plural in some channels' docs) is dropped — the server subscribes the consumer to a much broader stream than intended (all markets, all symbols).
  • params={'send_snapshot': True} (typo of send_initial_snapshot) is dropped — the consumer never gets a snapshot and has to wait for the first delta.
  • Any future server-added parameter is invisible to existing SDK clients with no warning.

This is the documented escape hatch for the two channels (control_frames, root) that don't have typed helpers, so users WILL hit it.

Location

kalshi/ws/channels.py:21-30, 48-54

Evidence

# kalshi/ws/channels.py:21-30
_SUBSCRIBE_FORWARD_KEYS = (
    "market_ticker",
    "market_tickers",
    "market_id",
    "market_ids",
    "shard_factor",
    "shard_key",
    "send_initial_snapshot",
    "skip_ticker_ack",
)

# kalshi/ws/channels.py:48-54
def to_subscribe_params(self) -> dict[str, Any]:
    """Build the params dict for the subscribe command."""
    result: dict[str, Any] = {"channels": [self.channel]}
    for key in _SUBSCRIBE_FORWARD_KEYS:
        if key in self.params:
            result[key] = self.params[key]
    return result  # ← unknown keys silently dropped

Recommended fix

Validate params against the channel's known parameter set at subscribe() time. Either:

Option A (minimal): Raise KalshiSubscriptionError from Subscription.__init__ (or to_subscribe_params) on unknown keys.

Option B (best): Define a per-channel dict[channel, frozenset[str]] of accepted params (with set semantics for the typed helpers + the public escape hatch), and raise on any key not in the channel's set. Drives off the AsyncAPI spec so it stays accurate.

Option C (highest fidelity): Add a typed SubscribeParams Pydantic model per channel with extra='forbid' to fail fast on typos — matches the existing request-body pattern.

Regression test: test_generic_subscribe_rejects_unknown_param_keys invokes ws.subscribe('orderbook_delta', params={'tickerz': ['X']}) and asserts KalshiSubscriptionError.

Severity & category

high / correctness, dx, ws

Activity

  1. added
    bugSomething isn't working
    wsWebSocket-related
    on May 21, 2026
  2. added a commit that references this issue on May 21, 2026
    f5db1a1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingwsWebSocket-related

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions