---
source_url: https://www.pubnub.com/docs/sdks/javascript/troubleshooting
title: Troubleshoot the PubNub JavaScript SDK
updated_at: 2026-11-09T13:29:01.000Z
sdk_name: PubNub JavaScript SDK
sdk_version: 13.1.3
description: Find the symptom, understand the cause, and apply the fix for common problems with the PubNub JavaScript SDK, from connection errors to missing presence events.
---

# Troubleshoot the PubNub JavaScript SDK

PubNub JavaScript SDK, use the latest version: 13.1.3

Install:

```bash
npm install pubnub@13.1.3
```

> For AI agents: documentation index at https://www.pubnub.com/llms-full.txt

Use this page to fix common problems in the PubNub JavaScript SDK by matching what you see in your app to its cause and fix. Status categories such as `PNConnectionErrorCategory` reach only the status listener that you add on the PubNub client, so add one before you troubleshoot. If your symptom is not listed, go to [Get help](#get-help).

Each entry gives the symptom as its heading, then the cause and the fix. For a decision tree that covers all PubNub SDKs, refer to [Troubleshoot PubNub request failures](https://www.pubnub.com/docs/design-patterns/troubleshooting.md).

## Connection

### The PubNub constructor throws a configuration error

* **Cause:** The constructor throws a `PubNubError` when `userId` is omitted, is empty or only whitespace, or is set together with `uuid`. The SDK sends no request first.
* **Fix:** Set a unique `userId` in the configuration when you create the PubNub instance, and set no `uuid`. Keep the `userId` unchanged for the lifetime of the user or the device. Refer to [Initialization errors](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration.md#initialization-errors).

### The subscription fails with PNConnectionErrorCategory

* **Cause:** The client could not establish the connection to the real-time updates stream. Permission errors and a network outage can both cause it. The `error` field of the status contains the specifics.
* **Fix:** Inspect the `error` field. If it contains `PNAccessDeniedCategory` (403), follow [Access is denied (403)](#access-is-denied-403). Otherwise, check the network connection. For all categories, refer to [Status events](https://www.pubnub.com/docs/sdks/javascript/status-events.md).

### The client disconnects unexpectedly

* **Cause:** The client lost its real-time connection. The SDK reports it as `PNDisconnectedUnexpectedlyCategory`, available from version 8.9.0 and when `enableEventEngine` is `true` (the default). With the legacy subscription manager (`enableEventEngine: false`), a lost connection can appear as `PNNetworkIssuesCategory`. That category means the client could not reach PubNub servers because of a network issue or a proxy.
* **Fix:** Read the `error` field on the status for the root cause. If the app runs in a browser, [configure](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration.md#configuration) the SDK to emit `PNNetworkDownCategory` and `PNNetworkUpCategory` when the network status changes. For how the SDK handles reconnection, refer to [SDK Connection Lifecycle](https://www.pubnub.com/docs/architecture/connection-management/overview.md).

### The status is PNUnknownCategory or PNMalformedResponseCategory

* **Cause:** The client received an unexpected response or hit an error that it could not categorize. Common causes are aborted requests (`errorData` contains `[Error: Aborted]`), non-standard HTTP responses from proxies or VPNs, and unhandled HTTP status codes. A `200` response with a body that is not JSON, an empty body, or an HTML page from a proxy also gives `PNUnknownCategory`, with `statusCode` `0`. In these cases the SDK does not report `PNMalformedResponseCategory`.
* **Fix:** Check the `statusCode` and `errorData` fields of the status. If a proxy or VPN sits between your app and PubNub, test without it. Refer to [Status events](https://www.pubnub.com/docs/sdks/javascript/status-events.md#request-statuses).

## Access

### Access is denied (403)

* **Cause:** The authorization key or token does not have the permissions the request needs, because of an [Access Manager](https://www.pubnub.com/docs/security/access-control/overview.md) failure. In a subscribe loop, the 403 appears as `PNConnectionErrorCategory` with `PNAccessDeniedCategory` in the nested `error` field.
* **Fix:** If the request is a subscribe, verify that your token has read permissions for the subscribed channels. [Check available permissions](https://www.pubnub.com/docs/security/access-control/check-permissions.md) to decode the token and see what it grants. If the token expired, follow [Update an expired token](https://www.pubnub.com/docs/security/access-control/update-expired-token.md). If someone [revoked it](https://www.pubnub.com/docs/security/access-control/manage-permissions.md#revoke-a-token), or a keyset setting or role changed, the [audit log](https://www.pubnub.com/docs/security/audit-log.md) shows who changed what and when.

## Publishing

### Publish fails with Message Too Large

* **Cause:** The message exceeds the size limit. A publish by POST (`sendByPost: true`) fails with HTTP 413 `Request Entity Too Large`, and a publish by GET (the default) fails with HTTP 414 `Request URI Too Long`. The SDK reports both as `PNUnknownCategory`. PubNub can process messages **up to 2 MB** in size, but the default message payload is limited to 32 KiB. This includes the channel name and any metadata.
* **Fix:** Reduce the payload below the limit. Refer to [Publish](https://www.pubnub.com/docs/pub-sub/publish/overview.md).

### Publish fails with PNBadRequestCategory or PNValidationErrorCategory

* **Cause:** A client without a `publishKey`, or a call without `channel` or `message`, fails before the SDK sends a request. The SDK reports `PNValidationErrorCategory` with the message `Missing 'publishKey'`, `Missing 'channel'`, or `Missing 'message'`. `PNBadRequestCategory` means PubNub answered the request with HTTP 400 because the request is malformed in another way. Refer to [Status events](https://www.pubnub.com/docs/sdks/javascript/status-events.md#request-statuses).
* **Fix:** Set `publishKey` in the configuration if you did not, and include both `channel` and `message` in the call. Refer to [Publish](https://www.pubnub.com/docs/sdks/javascript/api-reference/publish.md#publish).

## Receiving

### Logic tied to PNConnectedCategory runs only once after you upgrade

* **Cause:** Since SDK version 11.0.0, `enableEventEngine` defaults to `true`. `PNConnectedCategory` is now emitted only when the subscription starts. Changes to the channel or channel group mix emit `PNSubscriptionChangedCategory` instead.
* **Fix:** If logic ran on every subscribe or unsubscribe, move it to a `PNSubscriptionChangedCategory` handler. Keep `PNConnectedCategory` for the initial subscription start. Refer to [Migrating to the new subscription loop](https://www.pubnub.com/docs/sdks/javascript/status-events.md#migrating-to-the-new-subscription-loop).

### You need messages that were published while the client was not subscribed

* **Cause:** A subscription reports `PNConnectedCategory` when the client is ready to receive real-time updates. Earlier messages are not part of that stream.
* **Fix:** If Message Persistence is enabled on your keyset, fetch earlier messages with [Fetch history](https://www.pubnub.com/docs/sdks/javascript/api-reference/message-persistence.md#fetch-history). You can also pass a `cursor` with a timetoken when you subscribe, but retrieval with a cursor is a best-effort service and is not guaranteed. Refer to [Subscribe](https://www.pubnub.com/docs/sdks/javascript/api-reference/subscribe.md#subscribe). With the legacy subscription manager, `PNRequestMessageCountExceededCategory` means the client exceeded the configured [`requestMessageCountThreshold`](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration.md#configuration). Enable [Message Persistence](https://www.pubnub.com/docs/data-storage/message-history/overview.md) on the keyset to retrieve what the in-memory cache dropped.

## Presence

### Users appear to leave a channel without unsubscribing

* **Cause:** PubNub received no heartbeat or subscribe request from the client within `presenceTimeout`, so it marked the client offline and emitted a `timeout` event on the presence channel. PubNub SDKs set `presenceTimeout` to 300 seconds by default, which is how long PubNub waits without a heartbeat before marking a client offline. A lost network or a stopped app can stop the requests. By default, the client sends no periodic heartbeats between subscribe requests.
* **Fix:** If clients stay connected but still time out, set `heartbeatInterval` so the client sends explicit heartbeats often enough. To detect lost clients sooner, lower `presenceTimeout`, which also sets `heartbeatInterval` to half the presence timeout minus one second. Each explicit heartbeat is a billable API call. If you want an immediate leave event instead of a delayed timeout, unsubscribe before the client goes offline. Refer to [Configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration.md#configuration) and [Implicit heartbeats and the presence timeout](https://www.pubnub.com/docs/architecture/connection-management/overview.md#implicit-heartbeats-and-the-presence-timeout).

## Encryption

### Data uses legacy encryption although cryptoModule is configured

* **Cause:** A cipher key that you pass to a method overrides the configured crypto module for that operation and uses the legacy encryption with 128-bit cipher-key entropy. The cipher key arguments are `customCipherKey` for `encrypt()` and `decrypt()`, and `key` for `encryptFile()` and `decryptFile()`.
* **Fix:** To use the configured `cryptoModule`, remove those arguments. The module uses AES-256-CBC when you configure `PubNub.CryptoModule.aesCbcCryptoModule`. For partial encryption scenarios, configure a separate `cryptoModule` instance. Refer to [CryptoModule configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration.md#cryptomodule).

## Get help

### You need more detail than the status gives you

* **Cause:** PubNub SDK logging is disabled by default. The default level is `LogLevel.None`.
* **Fix:** Set `logLevel` to `PubNub.LogLevel.Debug` or `PubNub.LogLevel.Trace` when you create the instance, then reproduce the issue. Refer to [Logging](https://www.pubnub.com/docs/sdks/javascript/logging.md).

### You need to contact support

* **Fix:** Reproduce the issue with `LogLevel.Debug` or `LogLevel.Trace`, copy the console output, and send it to [support@pubnub.com](mailto:support@pubnub.com). Remove credentials, tokens, and message content from the output first, because these levels can log sensitive data, and do not leave either level enabled in production. Refer to [Sensitive data in logs](https://www.pubnub.com/docs/sdks/javascript/logging.md#sensitive-data-in-logs).

### You see an unfamiliar status category or HTTP code

* **Fix:** Look up the category in [Status events](https://www.pubnub.com/docs/sdks/javascript/status-events.md) and the HTTP code in [Error codes](https://www.pubnub.com/docs/design-patterns/error-codes.md).

## Related tasks

* [Status events](https://www.pubnub.com/docs/sdks/javascript/status-events.md). Look up every status category the SDK emits.
* [Logging](https://www.pubnub.com/docs/sdks/javascript/logging.md). Configure log levels and custom loggers.
* [FAQ](https://www.pubnub.com/docs/sdks/javascript/faq.md). Read why the SDK has two subscribe methods and why a cipher key overrides `cryptoModule`.
* [Error codes](https://www.pubnub.com/docs/design-patterns/error-codes.md). Look up the HTTP code behind a failed request.
* [Troubleshoot PubNub request failures](https://www.pubnub.com/docs/design-patterns/troubleshooting.md). Diagnose a failure across all PubNub SDKs.

Last updated at: 2026-11-09T13:29:01.000Z
