The WebSocket onerror event fires when a WebSocket connection encounters an error, but it deliberately provides almost no diagnostic detail due to browser security policies. The actionable information arrives in the subsequent onclose event, which includes a close code and optional reason string. Developers should treat onerror as a signal to trigger logging, user notification, and reconnection logic rather than as a source of debugging information. VideoSDK abstracts much of this complexity for real-time communication use cases by managing connection lifecycle internally.

Introduction

Real-time web applications live and die by the reliability of their underlying connections. Whether you are building a chat application, a live dashboard, a multiplayer game, or a video calling platform, the WebSocket protocol is often the transport layer of choice for bidirectional, low-latency communication between client and server.
But connections fail. Networks drop. Servers crash. Proxies misbehave. Firewalls block traffic unexpectedly. When any of these things happen, the browser fires the WebSocket onerror event, and how your application responds in that moment determines whether users experience a brief hiccup or a complete app failure.
The challenge is that the onerror event is notoriously unhelpful. It tells you something went wrong, but it does not tell you what, why, or how to fix it. This is by design, not by accident. Browser vendors intentionally limit the information exposed through onerror to prevent security leaks, but this leaves developers guessing when things break.
In this guide, you will learn exactly what the onerror event does, why it provides so little detail, how it relates to the onclose event and close codes, and how to build a production-grade error-handling strategy that keeps your real-time application resilient. We will also cover monitoring, diagnostics, and how platforms like VideoSDK handle connection management at a higher level so you can focus on application logic instead of transport-layer debugging.

Understanding the WebSocket onerror Event

The WebSocket onerror event is a lifecycle event that fires when an error occurs during a WebSocket connection's lifetime, whether during the initial handshake, an active data exchange, or a closing sequence.
The event object passed to your onerror handler is a generic Event of type error. Unlike many other web APIs, it does not carry a message, error code, stack trace, or any descriptive payload. The browser dispatches the event and moves on. Your handler receives a notification that something went wrong, and nothing more.
The event fires in several distinct situations. The most common trigger is a failed connection attempt, where the server is unreachable, refuses the connection, or returns an invalid HTTP response during the WebSocket handshake. It also fires when an established connection drops due to network interruption, when the server sends a malformed frame that violates the WebSocket protocol, or when a TLS error occurs during a secure connection.
According to the WebSocket API documentation maintained by Mozilla, the onerror event is always followed by an onclose event when the connection terminates. This pairing is critical to understand because onclose is where the useful information lives.

Why onerror Provides Little Detail

The sparse nature of the onerror event frustrates many developers, but it stems from a deliberate security design decision enforced by browsers.
The core concern is information leakage. If the browser exposed detailed error messages through onerror, a malicious script could probe network topology, discover internal server addresses, or distinguish between different types of server failures. For example, an attacker could use WebSocket connections to determine whether an internal service is running on a specific port by examining whether the error message indicates a connection refused versus a timeout. Browser vendors prevent this class of attack by providing only a generic error signal.
This means you will never see messages like connection refused by a specific host or TLS certificate expired in your onerror handler. The event is a binary signal: either everything is fine, or something is wrong. The specific reason is withheld.
This design forces developers to rely on server-side logs, network diagnostics, and the onclose event's close code to understand what actually happened. It also means that client-side error handling must be built around reaction patterns rather than diagnostic patterns. You log that an error occurred, you notify the user, and you attempt reconnection. The debugging happens elsewhere.

The Relationship Between onerror, onclose, and Close Codes

When a WebSocket connection encounters an error, the browser fires onerror first, then immediately fires onclose with a close code that carries the actual diagnostic value.
The onclose event provides three key pieces of information: a numeric close code, a reason string (which may be empty), and a boolean indicating whether the connection closed cleanly. The close code is the most important field because it follows a standardized set of values defined in RFC 6455, the WebSocket protocol specification.
Here are the most common close codes developers encounter in production:
  • 1000 (Normal Closure): The connection closed successfully and intentionally. No error occurred.
  • 1001 (Going Away): Either the client or server is shutting down. Common when a user navigates away from the page.
  • 1002 (Protocol Error): The peer detected a protocol violation, such as a malformed frame.
  • 1003 (Unsupported Data): The peer received a data type it cannot handle, such as binary data on a text-only connection.
  • 1006 (Abnormal Closure): The connection closed abnormally without sending or receiving a close frame. This is the code you see most often with network failures, server crashes, and firewall blocks. The browser sets this code automatically and you cannot send it manually.
  • 1008 (Policy Violation): The server rejected the connection due to a policy, such as failed authentication or a CORS violation.
  • 1011 (Internal Error): The server encountered an unexpected condition that prevented it from fulfilling the request.
  • 1015 (TLS Handshake Failure): The connection failed during the TLS handshake. Like 1006, this code is set by the browser and cannot be sent manually.
The critical insight is that onerror tells you something broke while onclose tells you how it broke. Your error-handling architecture should treat onerror as the trigger and onclose as the diagnostic source.
Architecture Diagram

Common Error Scenarios

Real-world WebSocket errors fall into four broad categories, each requiring a different response strategy from your application.

Handshake Failures

Handshake failures occur during the initial HTTP upgrade from a standard HTTP request to a WebSocket connection. The server might return an HTTP 401 or 403 status code, indicating an authentication or authorization problem. CORS misconfigurations are another frequent culprit, where the server does not include the proper headers to allow cross-origin WebSocket connections. Reverse proxies and load balancers can also interfere if they are not configured to forward the Upgrade and Connection headers correctly.
When a handshake fails, the browser fires onerror followed by onclose with code 1006. Because 1006 is a catch-all for abnormal closure, you cannot distinguish a handshake failure from a network drop on the client side alone. Server-side logs are essential here.

Network Drops and Timeouts

Network drops happen when the physical or logical connection between client and server is interrupted. This includes users switching between Wi-Fi and cellular networks, ISP-level outages, firewall rule changes, and NAT timeout expirations. Mobile devices are particularly prone to these issues as users move between coverage areas.
Timeouts are a related but distinct scenario. If no data flows across the connection for an extended period, intermediary devices like NAT routers or load balancers may silently drop the connection. Without heartbeat or ping-pong messages, neither side discovers the drop until the next attempted send, which triggers an error.

Server-Side Exceptions

Server-side errors occur when the WebSocket server process encounters an internal problem. This could be an unhandled exception in the server code, a database connection failure that the server depends on, memory exhaustion under heavy load, or an unexpected process crash.
When the server crashes outright, the client sees onerror followed by onclose with code 1006 because no clean close frame was sent. If the server catches the error and closes the connection intentionally, the client receives a code like 1011 (Internal Error) with an optional reason string.

Protocol Violations

Protocol violations are less common but do occur, especially when client and server implementations disagree on framing rules. A server might send a frame with an invalid opcode, or a client might send an oversized message that exceeds the server's configured maximum frame size. These violations trigger onclose with code 1002 (Protocol Error) or 1009 (Message Too Big), which are among the few codes that provide clear, actionable diagnostic information directly to the client.

Building a Robust Error-Handling Strategy

A production-grade WebSocket error-handling strategy treats onerror as a trigger and onclose as the decision point, then layers logging, user communication, and reconnection logic on top.

Logging the Error

When onerror fires, your first action should be to log the event. Even though the event carries no detail, recording that it occurred, along with a timestamp, the current connection state, and any recent activity, creates a breadcrumb trail that helps when correlating with server-side logs.
Include contextual information in your log entry: the WebSocket URL, the connection duration before the error, the number of messages sent and received, and whether the connection was in the connecting, open, or closing state. This context transforms a generic event into a useful diagnostic data point when combined with server logs and monitoring tools.

Interpreting onclose Codes

The onclose handler is where you translate numeric close codes into actionable application behavior. Map each code to a specific response: code 1000 means clean shutdown and requires no action, code 1006 means network failure and should trigger reconnection, code 1008 means an authentication problem and should redirect the user to re-authenticate, and code 1011 means a server error and should display a generic error message while alerting your operations team.
For user-facing messages, avoid exposing the raw close code. Instead, map each code to a human-readable message that explains what happened in plain language. Users do not need to know that close code 1006 fired. They need to know that the connection was lost and the application is trying to reconnect.

User Notification

User notification is about managing expectations during connection failures. The goal is to inform users without overwhelming them with technical jargon or repeated alerts.
For transient errors where reconnection is automatic, show a subtle non-blocking indicator like a banner or toast notification that says reconnecting and dismisses it when the connection restores. For persistent failures where reconnection is exhausted, show a more prominent message that explains the situation and offers a manual retry button. Never show raw error codes or technical messages to end users.

Reconnection Logic

Reconnection logic is the backbone of WebSocket resilience. The most widely recommended approach is exponential backoff with jitter, where the client waits progressively longer between retry attempts to avoid overwhelming a recovering server.
Start with a short delay of one second, then double it for each subsequent attempt: two seconds, four seconds, eight seconds, sixteen seconds, and so on. Add a random jitter of a few hundred milliseconds to prevent thundering herd problems when many clients reconnect simultaneously. Cap the maximum delay at a reasonable value like 30 seconds, and cap the maximum number of retries based on your application's needs.
After exhausting retries, fall back to an alternative transport if available. For applications that can tolerate higher latency, HTTP long polling is a common fallback. For real-time communication applications using platforms like VideoSDK, the SDK handles this reconnection logic internally, including automatic reconnection with backoff and fallback strategies, so developers do not need to implement it from scratch.
Architecture Diagram

Graceful Degradation

Graceful degradation is the final layer of your error-handling strategy. When reconnection attempts are exhausted, the application must transition to a degraded state rather than leaving the user staring at a frozen interface.
This might mean switching from real-time updates to periodic HTTP polling, disabling interactive features that depend on the WebSocket connection while keeping read-only features available, or displaying a clear message that the real-time service is unavailable and offering a page refresh option. The key principle is that the application remains usable in some form even when the WebSocket connection cannot be restored.

Monitoring and Diagnostics

Building error-handling logic into your client code is only half the battle. You also need observability into WebSocket connection health across your entire user base.

Using Browser DevTools

Modern browser developer tools provide several tools for debugging WebSocket connections. The Network tab in Chrome DevTools, Firefox Developer Tools, and Safari Web Inspector all show WebSocket connections as entries with a special protocol indicator. Selecting a WebSocket entry reveals a Messages tab that displays every frame sent and received, including timestamps, direction, payload type, and content.
The browser console shows onerror and onclose events as they fire, though the error messages are predictably generic. For more detail, use the browser's built-in network throttling and offline simulation features to test how your application behaves under poor network conditions. This is invaluable for validating your reconnection logic during development.

Server-Side Metrics

Server-side monitoring is where the real diagnostic power lives. Track metrics like total connection attempts, successful handshakes, failed handshakes, average connection duration, messages per connection, and connection close code distribution.
These metrics reveal patterns that client-side logging cannot. A sudden spike in 1006 close codes across many clients might indicate a network infrastructure issue. A rise in 1011 codes points to server-side problems. A high ratio of failed handshakes to successful ones might indicate an authentication service outage or a CORS configuration error introduced in a recent deployment.

Alerting and Observability

For production systems, integrate WebSocket metrics into your broader observability platform. Tools like Datadog, Grafana, Prometheus, or New Relic can ingest WebSocket connection events and create dashboards and alerts.
Set up alerts for error rate spikes, unusual close code distributions, and connection duration anomalies. When the percentage of connections ending with code 1006 exceeds a threshold, page the on-call engineer. When handshake failures spike, trigger an investigation into your reverse proxy or authentication service.
Architecture Diagram

Best-Practice Checklist

Here is a concise checklist of the key actions every developer should implement for WebSocket error handling:
  • Always attach an onerror handler to every WebSocket connection, even if it only logs the event
  • Always attach an onclose handler and inspect the close code to determine the appropriate response
  • Never expose raw close codes or technical error messages to end users
  • Map each close code to a user-friendly message and a specific application behavior
  • Implement exponential backoff with jitter for reconnection attempts
  • Set a maximum retry count and a maximum delay cap to prevent infinite reconnection loops
  • Provide a fallback transport mechanism when WebSocket reconnection is exhausted
  • Log onerror events with contextual metadata for correlation with server-side logs
  • Track server-side WebSocket metrics including close code distribution and handshake success rates
  • Set up alerts for error rate spikes and anomalous close code patterns
  • Test reconnection logic using browser DevTools network throttling and offline simulation
  • Consider using a managed real-time communication platform like VideoSDK to handle connection lifecycle, reconnection, and error recovery without building it from scratch

Definitions Glossary

WebSocket onerror event: A lifecycle event fired by the browser when a WebSocket connection encounters an error, providing a generic signal without diagnostic detail due to security restrictions.
onclose event: The WebSocket lifecycle event that fires after a connection closes, carrying a numeric close code and optional reason string that provide actionable diagnostic information.
Close code 1006: A standard WebSocket close code indicating abnormal closure where no close frame was sent or received, typically caused by network failures, server crashes, or firewall blocks.
Exponential backoff: A reconnection strategy where the delay between retry attempts doubles with each failure, reducing load on recovering servers and improving the probability of successful reconnection.
Handshake failure: An error occurring during the initial HTTP upgrade from a standard HTTP request to a WebSocket connection, often caused by authentication errors, CORS misconfigurations, or proxy issues.
Graceful degradation: An application design pattern where functionality is reduced rather than eliminated when a dependency fails, keeping the application partially usable during connection outages.

Key Takeaways

  • The WebSocket onerror event is a generic error signal that deliberately provides no diagnostic detail due to browser security policies designed to prevent information leakage.
  • The onclose event, which always follows onerror, carries the actionable information through its close code and reason string, making it the primary source for error diagnosis and response logic.
  • Close code 1006 is the most common code in production and indicates abnormal closure, typically caused by network drops, server crashes, or firewall blocks, but it cannot distinguish between these causes on the client side alone.
  • A robust error-handling strategy combines logging, close code interpretation, user-friendly notifications, exponential backoff reconnection, and graceful degradation into a layered defense against connection failures.
  • Server-side metrics and observability tooling are essential for understanding WebSocket error patterns across your user base, since client-side onerror events lack the detail needed for root cause analysis.
  • Platforms like VideoSDK abstract away WebSocket and WebRTC connection management, handling reconnection logic, error recovery, and fallback strategies internally so developers can focus on application features rather than transport-layer resilience.

Conclusion

The WebSocket onerror event is best understood as a signal, not a solution. It tells you that something went wrong, but the real work of diagnosis and recovery happens in your onclose handler, your server logs, and your monitoring infrastructure. By treating onerror as a trigger for logging and user notification, and by building reconnection logic around close code interpretation, you can create real-time applications that survive the inevitable connection failures of production environments.
For developers building video calling, audio rooms, or interactive live streaming features, managing WebSocket and WebRTC connection lifecycle from scratch is a significant engineering investment. VideoSDK handles connection management, automatic reconnection, network-adaptive streaming, and error recovery across ten or more platform SDKs, letting you focus on application logic instead of transport-layer debugging. You can explore the REST API reference for server-side orchestration or browse code samples to see how it works in practice.
What are you building with real-time communication? Drop a comment below, and I'd love to hear how you are handling WebSocket errors in your application. You can also join the VideoSDK Discord community to discuss connection management patterns with fellow developers.

Free $20 Balance for AI Voice Agents & Video Calls

FAQ