BadSecureChannelIdInvalid
BadLifecycle
BadSecureChannelIdInvalid means the SecureChannelId in your message header does not match any channel the server holds. It happens after a server restart, after the channel was closed, or when a client sends on a channel that belongs to a different connection. Open a fresh secure channel and re-establish the session.
What you actually see
Requests are rejected instantly with a channel-level error, often immediately after a reconnect attempt that appeared to succeed at the TCP layer.
Why it happens
- Server restarted and lost its channel tableSecureChannelIds are assigned by the server and held in memory. After a restart the client's cached id refers to nothing. If the client reconnected the socket but reused the old channel id, this is the exact failure you get.
- Client sent on a channel it had already closedA shutdown path or an error handler closed the channel while requests were still queued. Those requests reach the server with a now-unknown id. The equivalent transport-level rejection is BadTcpSecureChannelUnknown.
- Channel id used on the wrong socketA channel is bound to one transport connection. Multiplexing bugs, connection pooling, or a client that opens a second socket and reuses the first channel's id produce this immediately.
- Token renewal handled incorrectlyDuring RenewSecureChannel the channel id stays the same but the token changes. A client that instead treats renewal as a new channel, or that mixes the ids of two overlapping channels, will address a channel the server does not have.
- Load balancer sent the request to a different server instanceTwo servers behind one virtual address each keep their own channel table. Once a request lands on the instance that did not create the channel, the id is unknown there even though the client is perfectly correct.
How to fix it
In diagnostic order: work down, do not skip ahead.
- Check whether the server restartedRead Server_ServerStatus_StartTime after reconnecting, or check the server log. A restart makes this expected and moves the question to whether your client discards cached channel state properly.
- Prove there is exactly one server instance behind the endpoint URLResolve the hostname and compare the ApplicationUri and server certificate thumbprint across several connections. Different values from the same URL mean a load balancer or a DNS round-robin is splitting your channels.
- Discard all cached channel state on any channel errorOn BadSecureChannelIdInvalid, BadSecureChannelClosed or BadTcpSecureChannelUnknown, drop the channel id, the token and the derived keys, then open a new channel from scratch. Never retry the same request on the old id.
- Verify renewal keeps one channel identityCapture the handshake with the Wireshark OPC UA dissector and confirm OpenSecureChannel with request type Renew keeps the same SecureChannelId while issuing a new token.
- Re-establish the session on the new channelAfter the new channel is up, re-bind or recreate the session and then call TransferSubscriptions. If your stack cannot re-bind, recreate the session and accept the cost.
Where it shows up, by tool and stack
| Tool / stack | What to do there |
|---|---|
| UA-.NETStandard (C#) | The channel is owned by the transport channel object, not by the Session; disposing and recreating the channel is the correct response. Enable Utils tracing for the SecureChannel category to see id and token transitions. |
| open62541 (C) | The client tracks the channel in UA_SecureChannel with its own state enum. Errors here surface through the connect status; do not attempt to reuse a channel after any secure-channel-level error. |
| node-opcua | ClientSecureChannelLayer manages the id and token renewal. If you see this code, check whether application code is creating more than one channel against the same endpoint. |
| Kubernetes | Exposing an OPC UA server through a Service with more than one replica breaks channels this way. Use a StatefulSet with a stable per-pod endpoint, or one Service per replica, and never round-robin opc.tcp. |
| Wireshark OPC UA dissector | Shows SecureChannelId and TokenId on every UASC message, which makes it straightforward to prove whether the client or the server lost track of the channel. |
What it looks like in the log
Request rejected: BadSecureChannelIdInvalid (channelId=41)
Received message for unknown secure channel 41 from 10.20.3.15
Renewing secure channel 41: new tokenId issued, channelId unchanged
Confirm the fix
Reconnect and confirm a new OpenSecureChannel is issued and the new id is used on every subsequent message, with no further channel-level rejections over a sustained run.
Stop it happening again
Make channel state strictly disposable in client code, keep OPC UA endpoints pinned to a single server instance, and never place a round-robin load balancer in front of opc.tcp.
Stuck on more than one of these? The troubleshooting clinic works through broken configurations end to end, on camera.
Troubleshooting clinic →Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.