LM-Kit OneDocs2026.8.10lm-kit.com
Getting Started

Troubleshooting First Runs

The failures that show up before the first success, indexed by symptom. Each section stands alone: what the error means on this server, why it happens on a first run, and the shortest fix. Two commands recur throughout: lmkit doctor, the one-pass preflight, and lmkit logs, the log tail from any terminal.


1Find your symptom#

Start from what you are seeing, not from what you suspect:

Symptom Section
Connection refused from another machine 2
401 Unauthorized (or 403 Forbidden) on the first call 3
model_not_found / model 'x' not found 4
The first request hangs for minutes 5
503 errors, or the model will not load 6
Tokens arrive, but slowly 7
The server will not start at all 8
A browser app gets CORS errors 9
You need the logs, or a support report 10, 11

2Connection refused#

What it means. Nothing is listening at the address you called. By default the server binds loopback only: 127.0.0.1 and ::1, HTTP on port 5189 and HTTPS on 7221. From any other machine, the connection is refused by design, not by failure.

The fix. On the server itself, curl http://localhost:5189/health answers without authentication, and lmkit status exits 0 when a server is running (2 when not). If that works, the server is healthy and the posture is the cause: switch Local only to Network in the Network section and restart to rebind the listeners. Read Going Live first: once the posture is Network, every API call needs a key, so mint keys before flipping the switch. If localhost also refuses, the server is not running; section 8 covers why it might not start.

3401 or 403 on the first call#

What 401 means. No valid API key where one is required. A loopback-only server accepts keyless local calls while the anonymous toggle is on, which is why the Playground works with zero ceremony; a network-reachable server refuses keyless calls always, with no override.

The fix. Mint a key in Access and send it as Authorization: Bearer lmk_... on every dialect. One trap catches Anthropic SDK users: configure the key as auth_token (which sends the Bearer header), not as api_key. The x-api-key header is read for attribution but is deliberately not an authentication channel. Details in Keys and Authentication.

What 403 means. A different gate: the admin console's own protections (HTTPS-only enforcement, or an IP allowlist) refused you. That is console access policy, not API authentication; review the settings you enabled in Security.

4The model name is not recognized#

What it means. The request named a model this server does not have. All three dialects answer with 404: the OpenAI surface returns "The model 'x' does not exist or is not loaded." with code model_not_found, the Anthropic surface returns a not_found_error, and the Ollama surface returns model 'x' not found. The usual first-run cause is a client whose default model is a cloud name; this server serves its own catalog ids, and the same id works on every dialect.

The fix. Ask the server what it has: GET /v1/models (OpenAI clients), /api/tags (Ollama clients), or the Models section, which is the living catalog. Then either name a model that exists, or name none: a request without a model is served by the default for its capability, configured in the same section (see Choosing and Operating Models).

5The first request hangs#

What it means. Almost always: the model is not ready yet, and the request is waiting for it. Two waits stack on a first run. A catalog model that is not on disk yet is downloaded when first requested, and the request blocks until the download completes; progress is visible in the Models section. A model on disk but not resident loads on first use, and cold loads run one at a time, so concurrent first requests queue behind the load.

The fix. Pre-provision instead of paying on the first request: pull from the Models section, or headlessly with lmkit pull <model-id> (the catalog and per-model download state are lmkit models; see The Command Line). A download that fails outright is not a hang: lmkit pull exits 1 on an unknown id or a failed fetch, and lmkit doctor's model-directory and free-disk checks catch the usual causes. lmkit status --api-key <key> reports loaded models, active inferences, and queue depth, so "hung" and "working on it" are distinguishable. For long document jobs that outgrow a request, the async contract in Errors, Retries, and Jobs is the right shape, not a longer timeout.

6Out of memory at model load#

What it means. The model plus its working memory does not fit the device. A model's file size approximates its footprint at rest; context length adds working memory per active request on top. The server degrades rather than dies: it reduces what it keeps resident and falls back instead of taking the process down, and transient pressure surfaces to callers as 503 with Retry-After and reason service_unavailable, which is safe to retry.

The fix. Size against the device before pulling: the Hardware section shows what the devices offer, Hardware Sizing is the memory math, and The Right Model for Your Machine is the model-side answer (a smaller model or tighter quantization from the catalog). Sizing for concurrent load is Inference Capacity. Note that 413 with input_too_large is not a memory problem: the input exceeds what one inference pass can hold, and only shrinking the input fixes it.

7Tokens arrive, but slowly#

What it means. If throughput is an order of magnitude below what the hardware should give, the model is likely running on CPU instead of the GPU: a missing driver, a disabled backend, or weights that did not fit device memory and spilled to host.

The fix. Check what the runtime sees: lmkit devices prints the compute inventory (number, name, type, memory) and the Hardware section shows the same live. Backend setup, driver verification per platform, and confirming the GPU is actually doing the work are covered in GPUs and Backends. If the devices are visible but the model spills, section 6 applies: the fix is fit, not drivers.

8The server will not start#

What it means. The startup log (section 10) names the failure; the common first-run cause is a port conflict: another process already holds the configured port, so the bind fails. The classic occupant is a second copy of this server, since desktop mode (the tray) and the Windows service are two supervision styles for the same binary and should not both run.

The fix. lmkit status tells you whether the thing answering on the port is this server, and lmkit service status whether the Windows service is registered. Stop the duplicate, or move this instance: ports live in the Network section. Then run lmkit doctor: it checks the state directory and its writability, the model directory and free disk, visible devices, certificate validity, service registration, and liveness in one pass, and prints [ok] or [!!] per check.

9A browser app is blocked by CORS#

What it means. Server-to-server calls never see CORS; only JavaScript running in a browser on a different origin does. By default the server allows no cross-origin browser callers, so a web app served from elsewhere gets its requests blocked by the browser before they carry credentials.

The fix. Set CORS Origins in the admin console's General settings (the CorsAllowedOrigins setting): a comma-separated list of origins, or * for any. The change applies on restart. Prefer named origins: * means any website a user visits can call this API from their browser; the server warns about it in the startup log. Keys embedded in browser JavaScript are visible to anyone who opens the page, so mint a narrow key for that purpose (see Keys and Authentication).

10Where the logs are#

Everything the server writes lives under one state directory, decided at startup and named in the startup log: the executable's own directory when writable, otherwise the per-user data folder (%LOCALAPPDATA%\LM-Kit\One on Windows, ~/.local/share/LM-Kit/One elsewhere), with LMKIT_STATE_DIR pinning it explicitly. The log is logs/server.log under that directory; rotated archives sit beside it as server.1.log, server.2.log. Three ways to read it: the Logs section live with level filtering, lmkit logs -n 200 (add --follow to stream) from any terminal, or the file itself. CLI verbs act on the state of the OS user running them, so a service and a shell can see different paths; lmkit doctor prints the paths it acted on precisely so that mismatch is visible. The full inventory is Where Data Lives.

11What to capture for a support report#

Five artifacts turn a report from a symptom into a diagnosis:

  • lmkit doctor output. The environment in one pass; it is the first ask on any thread.
  • lmkit version and lmkit status. The executable's version and the running server's: after an upgrade they differ until a restart, and that difference is itself a finding.
  • The log tail. lmkit logs -n 200 around the failure; for a 500, the sanitized response body is deliberately generic and the full cause is only in the log.
  • The request record. The Requests section holds every call with route, status, and timing, and carries the exception summary for the operator.
  • The exact error body. The error and reason pair is stable and machine-readable (Errors, Retries, and Jobs); paste it verbatim. After a crash, include the unexpected-restart report from the Dashboard (Observability).

12Stated plainly#

  • Connection refused from another machine is the default posture working, not a bug: loopback only until you deliberately go to Network.
  • 401 means no key where one is required; a network-reachable server has no keyless mode.
  • Unknown model names answer 404 on every dialect; GET /v1/models and the catalog are the source of truth.
  • A hanging first request is usually a download or a cold load; pre-pull with lmkit pull and watch progress in the Models section.
  • lmkit doctor, lmkit logs, and the request record are the triage kit; capture all three before filing anything.