PlatformRealtime

Realtime troubleshooting

Find why a live update did not reach your client, then fix the channel, token, connection, or publish call.

Most missed updates come from one of five places: the publish call, the token, the channel name, the topic list, or the connection. Work through the sections below in order. For a known-good publisher and subscriber to compare against, see the Quick start.

The client receives no messages

  1. Check that publishing ran. Open the function run. A step.realtime.publish() call appears as a step in the trace. For inngest.realtime.publish(), check that the code path ran and that the awaited call didn't throw.
  2. Compare resolved channel names. A publisher on job:123 doesn't reach a subscriber on job:124. Compare the channel in the publisher, the token, and useRealtime.
  3. Compare topics. The publisher, the token, and useRealtime({ topics }) must all include the topic. A token grants only its listed topics.
  4. Check subscription timing. Realtime delivers messages only to clients connected when they're published. Wait for connectionStatus to be open before you start the work that publishes the first update. A tab that was hidden also misses messages published while it was paused.
  5. Check the hook's retained messages. messages.byTopic.status holds only the latest status message. messages.all keeps up to historyLimit messages, 100 by default. A bufferInterval delays renders while it batches messages.

See Channels and topics for definitions and React hooks for hook state.

Publishing fails with a schema error

Compare the payload with the topic's required fields and types, and import the same channel definition in the publisher and subscriber. A runtime validator such as Zod rejects mismatched data when you publish. staticSchema<T>() checks types only at compile time, so a mismatch can reach the subscriber, which logs a validation error. If only the subscriber reports errors, check whether the publisher and subscriber deployed different schema versions.

The client cannot connect or gets an authorization error

  • Mint on the server. Call getClientSubscriptionToken() on your server and send the { key, apiBaseUrl } object to the browser. The signing key must stay on the server.
  • Match the scope. The token's channel and topics must cover what useRealtime requests. Pass channel and topics to the hook too; the client token doesn't contain them.
  • Match the environment. Compare apiBaseUrl with the environment where the publisher runs. Locally, set INNGEST_DEV=1 on the server that mints tokens.
  • Refresh tokens. Pass a token factory so the hook gets a fresh token when it reconnects.

Never mint a token for an unchecked channel ID from the browser. See Subscription tokens.

The connection closes or keeps reconnecting

Inspect connectionStatus and error.

  • paused comes from enabled: false or a hidden tab while pauseOnHidden is true. pauseReason says which.
  • closed follows a completed, failed, or cancelled run while autoCloseOnTerminal is true.
  • error comes with a matching error value.

The hook reconnects by default. If reconnecting fails, check the token factory, the user's current access, and apiBaseUrl. When the job or channel ID changes, pass the new channel or change the hook's key to reset state and reconnect. reset() clears retained messages, result, and error.

The UI shows repeated progress or tokens

inngest.realtime.publish() sends immediately and isn't memoized, so it publishes again when the surrounding work retries. A call outside any step can also repeat when the function resumes after a wait. To fix repeats:

  • Use step.realtime.publish(id, topic, data) for state changes and final results, with a stable, unique step ID.
  • Move immediate publishes inside step.run().
  • For a token stream, let the UI tolerate repeats, for example by resetting the streamed text when the step restarts.

A server-side subscriber receives nothing

Check the channel and topics passed to subscribe({ app: inngest, ... }) or inngest.realtime.subscribe(). Read the returned stream or pass onMessage; creating a subscription alone doesn't process messages. Pass onError to see connection errors, and subscribe before the work publishes. See Server-side subscriptions.

Capture useful facts

When you ask for help, include the resolved channel name, topic, function run ID, publish method, connectionStatus, error, the token route's response status, and whether the tab was hidden. Don't include token keys or signing keys.

Next steps

  • Overview explains how messages reach clients.
  • Guides cover tokens, React, AI streaming, and server-side subscriptions.
  • Reference lists every Realtime API.
  • Limits covers connection and message allowances.