Skip to content

Error: Timeout waiting after 1000ms

The number is the diagnosis. One second is far too short to be a request to a language model, so whatever gave up here was waiting on something local: a process, a handle, a lock, a socket, a file. That rules out the vendor being down, your API key, your quota, your context window and your network path in a single stroke — none of those can be established, exhausted or exceeded inside 1000 ms.

Data as of 2026-09. Vendor limits and defaults change; check the official docs for current values before acting on any number below.

Why the number settles it

Claude Code’s per-request API timeout, API_TIMEOUT_MS, defaults to 600000 ms. That is the budget for something that has to cross the internet and wait for a model to think. A one-second budget is three orders of magnitude smaller, and nobody writes that for a network call on purpose.

The per-tool-call limit for MCP servers is larger still — when MCP_TOOL_TIMEOUT is unset the default is about 28 hours. So if the operation that failed were governed by either of the timers people usually reach for, the number in your message could not have been 1000.

What is left is the class of waits that are supposed to complete immediately: acquiring something already available, connecting to something already listening, reading something already on disk, or waiting for a child process that has already started to signal that it is ready. A one-second budget is what you write when you expect the answer in single-digit milliseconds and want a failure rather than a hang.

“Waiting” is a different verb from “request”

The message does not say a request failed or a response was slow. It says something was waiting. A wait is a poll on a condition — is it ready yet? — and it ends either when the condition becomes true or when the budget runs out.

That distinction changes what you look for. There is no round trip to inspect, no status code, no request id, and no headers. There is only a precondition that did not become true in time. The error string tells you almost nothing about which precondition; the line immediately above it in your output almost always does. Scroll up. The operation that was in progress when this fired — a server starting, a tool call dispatching, a file being opened, an editor integration attaching — is the actual subject of the page you are reading.

And 1000 is a round number, which is another piece of information: it is a default that shipped with something, not a value anyone chose for your machine. Defaults are calibrated for the case where everything is warm and local.

Is retrying useful?

Yes — retry once. It is the cheapest experiment available, and the result of that single retry is the branch point for everything else.

A one-second budget is easily lost to ordinary desktop noise: a security scanner opening a file before your process gets it, a cold page cache, a laptop resuming from sleep, CPU contention while a build or test suite is running, or a read that has to cross a virtual machine’s file share instead of hitting a local disk. None of those are broken; they are slow at exactly the wrong moment. Under any of them the same operation succeeds on the next attempt with no change from you.

The branch point is this: if the retry succeeds, you had a contention problem; if it fails instantly and identically, you have a deterministic one, and no amount of extra waiting will help because the condition is never going to become true. Do not build a longer retry loop before you know which one you have — a loop that eventually succeeds hides a contention problem you could have fixed, and a loop that never succeeds just makes a fast failure slow.

Telling the two apart

Run the same operation five or ten times. This is the whole test. Occasional failures mean contention; failure on every attempt means a broken precondition. Everything below depends on which of those you saw, so do not skip it.

Read the lines above the error. Whatever the tool was doing when it fired names the component that was waiting. If nothing above it is informative, run the tool with debug output enabled — /debug inside a session turns on debug logging and asks Claude to diagnose, and the per-session debug log is written under your config directory.

Start with everything customized turned off. claude --safe-mode runs with all plugins, MCP servers and hooks disabled. If the message disappears, the wait belongs to one of those, not to the core tool, and you can re-enable them one at a time until it comes back. This is the fastest way to convert a generic string into a named culprit.

Check whether the work crosses a filesystem boundary. A wait budget that is generous against a local disk is marginal against a share between a host and a virtual machine. If your project lives on a Windows drive that a Linux guest reaches over a share, or on a network drive, that alone can turn a comfortable one-second wait into a coin flip.

Ask who printed it. A bare Error: with no component name often comes from a wrapper rather than from the CLI itself — the same way Error: Claude Code process exited with code 1 is printed by VS Code or an SDK application and identifies nothing on its own. If an IDE extension or your own script is in the chain, check its output before assuming the tool underneath it is at fault.

Check whether you configured a small timeout yourself. There is one place in Claude Code’s own configuration where 1000 is a meaningful boundary: the per-server MCP timeout, where values below 1000 are ignored. If you set that option to a small number believing it was in seconds, you did not get what you intended. Take the current unit and accepted range from the documentation rather than from this page.

Fixes, keyed to what the repetitions showed

  • Occasional, and it correlates with load — retry, and then remove the contention rather than the message. Running a full test suite, a large build or an antivirus scan in parallel with the tool is enough on its own. This is a legitimate place to stop: an intermittent one-second wait on a busy machine is not a defect.
  • Occasional, and the work is on a shared or network filesystem — move the project onto a local disk on the side that is doing the work. Crossing that boundary is slow enough to matter and, in Claude Code specifically, the documentation notes that searches spanning the WSL filesystem boundary return fewer results than expected while claude doctor still reports Search as OK. A boundary that degrades tooling silently is not where a repository belongs.
  • Deterministic, and --safe-mode fixes it — one of your plugins, MCP servers or hooks is waiting for something that never arrives. Re-enable them one at a time. For an MCP server, the startup timer is MCP_TIMEOUT and the per-call limits are separate; a server that never finishes starting is a different fault from one that starts and then hangs.
  • Deterministic, and it survives --safe-mode — the precondition itself is broken: something is not running, not listening, or not present. The fix is in that component, and the surrounding log lines identify it. Raising any timeout here converts an instant failure into a slow one and nothing else.
  • You are on a version older than the one you assumed — run claude --version and check the current documentation. The docs version-gate individual behaviours, and the wording of these messages changes often, sometimes within a minor version.

How to confirm it’s fixed

Repetition is the only honest test, because a single clean run is exactly what a contention problem produces by luck. Run the operation five times in a row without the message appearing, and run them under the same conditions that produced it — if it only failed while your test suite was running, confirm it while your test suite is running.

For the deterministic case, confirm the precondition rather than the silence. If an MCP server was the culprit, /mcp should show it connected. If a file or socket was being waited on, check that it exists and responds. A quiet terminal proves only that nothing timed out this time.

Timeouts with a much larger number in them are a different animal: they usually did involve the network, and the budget in the message tells you which layer set it. If a login flow gave up, see OAuth error: timeout of 15000ms exceeded; if the installer could not fetch a version, see timeout while fetching the version from stable.

If your tool is counting down a retry interval measured in minutes rather than failing in one second, nothing local is stuck and the problem is on the network path: No response from API with a multi-minute retry explains what a long interval implies. If an MCP server is the component that went quiet, MCP error: Connection closed covers a server that dies rather than one that is merely slow to answer. And if a short wait only fails when your files live across a virtual machine share, Plan9 mount failed: invalid argument is what that boundary looks like when it fails outright instead of merely dragging.

When the message is this generic, the fastest way to place it is by layer rather than by wording: the AI coding error triage tool sorts errors by which component produced them and whether anything ever left your machine.