C# / .NET · recipe
Handle errors and reconnect in C#
Use SessionReconnectHandler. It re-establishes the session and attempts to transfer your subscriptions, which is far better than tearing everything down and rebuilding it. Classify the status code before deciding to retry at all.
| Stack | OPCFoundation/UA-.NETStandard |
|---|---|
| Version | 1.5.378.156 stable, 2.0.0-preview.2 |
The code
SessionReconnectHandler reconnectHandler = null;
session.KeepAlive += (s, e) =>
{
if (!ServiceResult.IsBad(e.Status)) return;
Console.WriteLine($"keep-alive failed: {e.Status}");
if (reconnectHandler != null) return; // already reconnecting
reconnectHandler = new SessionReconnectHandler(reconnectAbort: true);
reconnectHandler.BeginReconnect(session, 5000, (sender, args) =>
{
if (!ReferenceEquals(sender, reconnectHandler)) return;
session = (Session)reconnectHandler.Session;
reconnectHandler.Dispose();
reconnectHandler = null;
Console.WriteLine("reconnected; subscriptions transferred where the server allowed it");
});
};
// classify before retrying - not every failure deserves one
static bool IsWorthRetrying(StatusCode code) => (uint)code switch
{
_ when code == StatusCodes.BadCertificateUntrusted => false, // needs a human
_ when code == StatusCodes.BadUserAccessDenied => false, // needs a human
_ when code == StatusCodes.BadServiceUnsupported => false, // server cannot do it
_ when code == StatusCodes.BadSessionIdInvalid => true, // transient
_ when code == StatusCodes.BadConnectionClosed => true, // transient
_ when code == StatusCodes.BadTcpServerTooBusy => true, // transient, back off hard
_ => true,
};
What it prints
keep-alive failed: BadConnectionClosed
reconnected; subscriptions transferred where the server allowed it
Notes
- SessionReconnectHandler is the supported path. It tries TransferSubscriptions first, which preserves your monitored items and their queues.
- Hook the KeepAlive event. It is how you learn the session died promptly instead of at the next read.
- Never retry a certificate or identity error. It will fail identically forever until someone edits a trust list, and a retry loop just buries the log line that would have told you.
- Stagger and jitter reconnects across a fleet. Two hundred clients reconnecting together will finish what the network blip started.
- After reconnecting, confirm your monitored items are still reporting. A transferred subscription is the good case; a silently dead one looks identical from the outside.
What breaks first
A fleet reconnects in lockstep and the server refuses new sessions
Add jitter and a backoff cap to the reconnect delay, and cap concurrent session creation from your own collectors.
BadTcpServerTooBusyAdd jitter and a backoff cap to the reconnect delay, and cap concurrent session creation from your own collectors.
Other recipes in this stack
Concepts on this page
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.