# AR51.Net Troubleshooting (C# API)

Fixes for common **AR51.Net** problems. Turn on [logging](/docs/csharp-api/connecting/#logging) first — it shows connecting, reconnecting and refused requests.

<div className="apiTable">

| Symptom | Cause | Fix |
|---|---|---|
| **`StartAsync` never returns** | The server isn't found: discovery is blocked (another subnet, firewall, VPN), or the system is off | Connect to a [fixed host](/docs/csharp-api/connecting/#connect-to-a-fixed-host): `AR51Client.Create(new AR51ClientOptions { Host = "192.168.1.20" })`. Give `StartAsync` a token with a timeout to stop waiting. |
| **Works on your computer, but `StartAsync` hangs in Docker or WSL 2** | UDP broadcast discovery doesn't leave a Docker bridge network or WSL 2's NAT | Set `Host` to the AR 51 server's address, or run the container with host networking. |
| **`AR51Exception` with `ServiceUnavailable`** | The client isn't started yet, or that service isn't running on the system | Call `await ar51.StartAsync()` first; check the AR 51 servers are running (`ar51.Servers`). |
| **`ServiceUnavailable` for cameras, calibration or servers, but skeletons work** | Those services run on other AR 51 machines that aren't up | Launch the missing machines' server program (`ar51.Servers.LaunchServerAsync`), or check them in Mocap Studio. |
| **`Rejected`** | The server refused the request; the message says why (for example "A calibration is already running", "Restart too soon", an unknown camera id). Starting a recording while one is already running is also `Rejected`: "A recording is already running. Stop it first." | Read `exception.Message`, fix the request, or try again later. |
| **Some joints are (0, 0, 0)** | The cameras didn't see those joints | Use `skeleton.TryGetPosition(joint, out var position)` or check `GetConfidence(joint)`. |
| **`LeftHand` / `RightHand` are always `null`** | Hands come only from a hand-tracking headset worn by that person | Expected without such a headset. |
| **Events stop or lag** | A handler is too slow — skeleton handlers run on the receiving thread | Keep handlers short; copy the data and process it on another thread — see [hand-off patterns](/docs/csharp-api/app-integration/#hand-data-off-the-receiving-thread). |
| **A standalone `SkeletonClient` stops working after a server restart** | Service ports are assigned by the system and can change | Use `AR51Client`, which finds the services for you. |
| **`ObjectDisposedException`** | The client was used after it was disposed | Keep one client for the application's lifetime. |
| **The log says "declined discovery"** | The client sends its discovery protocol version, and the AR 51 server doesn't accept it | Use matching versions: update the AR51.Net package or the AR 51 server. |

</div>

AR51.Net is tested with AR 51 server **3.2.0** and **3.2.1**.

## Firewall and network checklist

- Outgoing **UDP 1500** — discovery broadcast (not needed with a fixed `Host`).
- **TCP 1501** to the AR 51 server — registration.
- **TCP** to the AR 51 machines on the ports the system assigns to its services.
- Your computer and the AR 51 machines on the **same subnet** for discovery.

## See also

- [Connecting](/docs/csharp-api/connecting/)
- [Data conventions, threading and errors](/docs/csharp-api/conventions/)
- [AR 51 network setup](/docs/network/network-overview/) and the [troubleshooting FAQ](/docs/troubleshooting/faq/)
