Skip to content

Learn

Exchange APIs

IBKR error 326: client id is already in use — how to fix it

Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs.

The message, identical in IBKR’s current and legacy TWS API error tables:

Unable to connect as the client id is already in use. Retry with a unique client id.

In one line: the socket to TWS or IB Gateway opened, but another API client is already connected to that session with the client ID you asked for. IBKR’s note on the code says exactly that. The interesting question is never what it means but who is holding the ID — and the answer is often a process you thought had stopped.

This is for anyone running TWS API code (official clients or wrappers) who sees 326 on connect, especially after a crash, a restart, or adding a second tool against the same TWS.

What this error actually means

Every TWS API connection is a connect(host, port, clientId) call. IBKR documents that each TWS session can receive up to 32 client applications simultaneously, and that the client ID is what distinguishes them. Two live connections cannot share one ID within a session, so the second is refused.

Three things follow from that mechanism:

  • The socket worked. Unlike error 502, 326 means your host, port and API settings are fine. TWS is running, the API is enabled, and it answered. Do not go looking at ports.
  • The conflict is with a live connection, from TWS’s point of view. Not with a process that is alive from yours. If TWS still believes an old socket is connected, the ID is held, whether or not the program that opened it still exists.
  • It can show up as an exception, not only as a code. IBKR’s documentation on broken socket connections notes that the exception raised in the EReader thread when a socket breaks also occurs when a client attempts to connect with an ID already in use. Depending on your library, you may see a reader-thread exception, the 326 message through EWrapper.error(), or both.

The usual cause

Two clients using the same default ID. Client ID 0 is documented as the recommended choice for optimal order-management behaviour, and a great deal of example code, and many tools, use it. That is how you end up with an MCP server, a Jupyter notebook and a monitoring script all asking for clientId=0 against the same TWS. The first one to connect wins; everything after it gets 326.

The fix is an assignment, not a retry: give every consumer its own fixed client ID, write the mapping down, and read the ID from configuration rather than from each tool’s default.

ConsumerClient ID
Order-managing strategy0
MCP server (read-only use)11
Research notebook21
Monitoring / reconciliation31

The numbers are an example. What matters is that they are distinct, stable and recorded somewhere other than inside each program. If you ever find yourself at the 32-client ceiling, you have a different design problem.

Other causes, in order of likelihood

A ghost session from a crashed or killed process. A script dies — killed from a terminal, a kernel restart, an unhandled exception in another thread — and TWS still treats its connection as open. Your restarted script asks for the same ID and is refused. We did not find a documented timeout after which TWS releases the ID, so do not build logic that waits a fixed number of seconds and assumes it will be free. Closing TWS or IB Gateway ends every API socket it holds; that is blunt, but it is certain.

A reconnect race. Reconnection logic calls connect() again before the previous connection has been fully torn down, or two reconnect paths fire at once (a watchdog and the library’s own auto-reconnect, say). The new attempt collides with the old one using the same ID. The pattern to look for in logs is 326 appearing only immediately after a disconnect. Make disconnect explicit, wait for it to complete, then reconnect with backoff — WebSocket reconnection patterns covers the same discipline for streaming connections.

Re-running the connect step inside a live process. In a notebook, running the connect cell a second time creates a second client with the same ID while the first is still connected. The same happens in any long-running process that constructs a new client object without disconnecting the old one.

The same code deployed twice. Two copies of a service, a scheduled job that overlaps with its previous run, or a web server that starts several worker processes, each reading the same CLIENT_ID from the environment.

Why not just pick a random ID?

It is tempting to catch 326 and retry with a different number. It will usually connect. It also hides the problem: the old connection is still there, still holding its ID, and possibly still running whatever it was doing. You now have two copies of your logic attached to one account, which is the situation you least want with anything that can place orders.

For a read-only consumer, a fallback ID is a reasonable convenience. For the client that manages orders, it is not — keep that ID fixed, and treat 326 on it as a signal to find and stop the other holder. The IBKR documentation singles out client ID 0 for order management, which is another reason to keep that one stable rather than rotating it.

How to confirm which one you have

  1. Log the client ID at every connect attempt, with the process ID and the port. When 326 arrives you want to know which program asked for which ID.
  2. List what is actually running. Check for a previous instance of the same program (ps, Task Manager, your process supervisor, open notebook kernels). A surviving process means a real duplicate, not a ghost.
  3. Try a different, unused ID once, by hand. If it connects immediately, the original ID is held by something TWS considers connected — a duplicate or a ghost. If it also fails, you are looking at a different error; read the code.
  4. Look at the timing. 326 only after disconnects points to a reconnect race. 326 on the very first start of the day points to another tool with the same default.
  5. If nothing you can find is holding it, restart IB Gateway or TWS. It clears every session, and if 326 disappears afterwards you had a ghost.

Keep 326 in the “permanent until something changes” class of errors: retrying the same ID in a tight loop cannot succeed until the other holder goes away. Error handling patterns for trading APIs explains why that class should fail loudly.

FAQ

What does IBKR error 326 mean?

It means another API client is already connected to the same TWS or IB Gateway session with the client ID you requested. The socket itself opened successfully; TWS refused the connection because client IDs distinguish up to 32 simultaneous API clients per session, and two connections cannot share one. Connect with a unique ID, or find and stop the other holder.

How long does TWS take to release a client ID after my script crashes?

We did not find a documented release timeout. Do not assume a fixed wait will free it. If the previous process is gone and the ID is still refused, restarting TWS or IB Gateway closes every API connection it holds and releases all client IDs with them.

Can two programs use client ID 0 at the same time?

Not against the same TWS session. Client ID 0 is documented as recommended for order-management behaviour, which is why so many tools default to it — and why two of them collide. Reserve 0 for the one client that manages orders and give every other tool its own fixed ID.

Is error 326 a login or permission problem?

No. Your API settings, port and host are working, because the socket opened and TWS answered. The refusal is purely about the client ID being in use by another connection. Credentials and permissions are not involved.