Skip to content

Troubleshooting

Start with thinkless doctor. It prints the Python and torch versions, the accelerator, which optional backends are installed, which API keys are set and the active settings.

Installation

ModuleNotFoundError for laya, gliner2, transformers, openai or anthropic. Local models and hosted backends are optional extras. Install what you use, for example pip install "thinkless[gliner,laya,local-llm]" or pip install "thinkless[all]".

pip wants to install transformers 5. GLiNER2 requires transformers<5, and every ThinkLess local extra shares that bound. If another package in your environment needs transformers>=5, give ThinkLess's local models their own environment.

CUDA is not available on an RTX 50 series card. Blackwell GPUs need PyTorch built for CUDA 12.8 or newer. Install from the matching index, for example pip install torch --index-url https://download.pytorch.org/whl/cu130. environment.yml does this for you.

requires the protobuf library when loading GLiNER. The DeBERTa tokenizer needs protobuf and sentencepiece. The gliner extra installs both; install them manually if you installed gliner2 on its own.

First model download

OSError: [WinError 1314] A required privilege is not held by the client. The Hugging Face cache uses symbolic links, and on Windows a parallel download can hit a race in the symlink check. Run the command again; the partial download is reused. Downloading serially avoids the race: huggingface_hub.snapshot_download("<model>", max_workers=1). Enabling Windows Developer Mode, which allows symlinks without administrator rights, avoids it entirely.

The first run is slow. Models download on first use: about 0.9 GB for Laya, 0.8 GB for GLiNER base and 3.4 GB for Qwen3-1.7B. Later runs load from the cache in seconds.

Running

Out of memory on the GPU. Laya, GLiNER base and Qwen3-1.7B peak at about 6.7 GB together. On smaller cards, move the decision models to the CPU (GLiNER(device="cpu") stays fast), or serve the LLM from another machine through an OpenAI-compatible server.

Everything is suddenly ten times slower on Windows. Another process is probably holding GPU memory. On Windows the driver does not fail when video memory runs out; it quietly spills into system memory, and every model slows down by an order of magnitude. Laya going from 30 ms to over a second per call is the typical sign. Check nvidia-smi, and run one GPU workload at a time (two benchmark processes each load their own copy of the models).

Generation is slow. TransformersLLM runs the plain Transformers generation loop, about 22 tokens per second for Qwen3-1.7B on a laptop GPU. Serving the same model with Ollama, vLLM or llama.cpp is several times faster; point OpenAICompatibleLLM at it.

Local LLM answers change between runs. They should not: decoding is greedy. If you pass a custom generation config to your own model wrapper, note that Transformers replaces values that equal its library defaults with the checkpoint's defaults unless use_model_defaults=False is passed.

A decision is always uncertain. Every provider answered below threshold. Check the trace: the attempt spans show each provider's confidence. Either the threshold is higher than the providers can reach on that question (run thinkless calibrate), or the question is ambiguous and needs clearer option descriptions.

A question always escalates to the LLM. The small models reach it but rarely clear its threshold. Calibrate, then either lower the threshold for that provider (thresholds={"question@provider": ...}) or remove the provider from the question (providers=(...)) so it stops adding latency.

Warnings from Laya about "invalid temperatures". Laya's checkpoint ships calibration temperatures only for smaller option counts; for choices with more than about ten options it warns and falls back. Treat its confidence on those questions with care, and calibrate.

Hosted models

Empty replies or every LLM decision abstaining. The model is probably reasoning by default and spending the whole token budget before it answers. Run with --reasoning off (or low). LLMDecider retries once with a larger budget and logs a warning when this happens; the attempt span shows truncated: true.

OpenRouter needs an API key. Put OPENROUTER_API_KEY=... in .env in the directory you run the CLI from, or export it.

OpenRouter's dashboard shows less spend than the traces. Its key usage figure lags by a few minutes. The costs on spans come from each response and are immediate.

A model rejects response_format. The client retries without JSON mode and logs a warning once; decisions keep working through the prompt.

Traces

No trace files appear. Traces are written by a JSONLSink. The CLI writes to THINKLESS_TRACE_DIR (default .thinkless/traces); in your own code, pass Tracer([JSONLSink(path)]) to the engine.

Traces contain [redacted]. Content capture is off (THINKLESS_CAPTURE_CONTENT=false or Tracer(capture_content=False)).