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.

StackOPCFoundation/UA-.NETStandard
Version1.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 BadTcpServerTooBusy
Add jitter and a backoff cap to the reconnect delay, and cap concurrent session creation from your own collectors.

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.

Free download
OPC UA Troubleshooting & Integration Checklist
The field-tested checklist engineers use to diagnose certificates, ports and namespace problems fast, plus a Python (asyncua) client template.
Get the free checklist →
Free, no course, no login