Troubleshooting Guide¶
Quick reference for the most common problems users encounter with tldw_server. Each entry includes the symptoms you see, the likely cause, and step-by-step fixes.
Tip: Before diving in, run
curl http://localhost:8000/healthto confirm the API is reachable. If this fails, start with Connection Issues.
Table of Contents¶
- Connection Issues
- Authentication Issues
- Chat and LLM Issues
- Media Ingestion Issues
- Transcription and Audio Issues
- Docker Issues
- Database Issues
- Multi-User and JWT Issues
- CORS and Browser Issues
- Embedding and RAG Issues
- MCP Issues
- WebUI Issues
- Performance Issues
- Installation Issues
Connection Issues¶
1. "Connection refused" when hitting the API¶
Symptoms: curl: (7) Failed to connect to localhost port 8000: Connection refused
Fix:
1. Verify the server process is running: ps aux | grep uvicorn (local) or docker compose ps (Docker).
2. If nothing is running, start it: make quickstart-local (local) or make quickstart (Docker).
3. If the server crashed on startup, check the logs for the root cause (import error, missing config, port conflict).
2. Server starts but WebUI shows blank page or "can't reach your tldw server"¶
Symptoms: Browser loads but shows a connection error or empty screen.
Fix:
1. Confirm the API is healthy: curl http://localhost:8000/health
2. If the API is up but the WebUI cannot reach it, check that both are on the same origin (the Docker quickstart uses a proxy to avoid this).
3. If you run the API and WebUI separately, set ALLOWED_ORIGINS in .env to include the WebUI origin (e.g., http://localhost:3000).
4. Check the browser console (F12) for specific error messages.
3. "Port already in use"¶
Symptoms: ERROR: [Errno 48] Address already in use or bind: address already in use
Fix:
1. Find what is using port 8000: lsof -i :8000 (macOS/Linux).
2. Stop the conflicting process, or start on a different port:
uvicorn tldw_Server_API.app.main:app --port 8001
-f, such as Dockerfiles/docker-compose.yml, Dockerfiles/docker-compose.single-user.yml, or Dockerfiles/docker-compose.multi-user-postgres.yml. If you maintain your own root-level docker-compose.yml, edit that file instead.
Authentication Issues¶
4. "401 Unauthorized" on every request¶
Symptoms: API returns {"detail": "Unauthorized"} or 401 status.
Fix (single-user mode):
1. Retrieve your API key: make show-api-key or check SINGLE_USER_API_KEY in tldw_Server_API/Config_Files/.env.
2. Pass it in every request header: -H "X-API-Key: YOUR_KEY_HERE"
3. Ensure the key is at least 16 characters.
Fix (multi-user mode):
1. Verify your username and password are correct.
2. Obtain a JWT token via the /api/v1/auth/login endpoint first, then use it as Authorization: Bearer <token>.
5. "API key too short"¶
Symptoms: Server refuses to start or returns 422 with a message about key length.
Fix: Generate a proper key (minimum 16 characters):
python -c "import secrets; print(secrets.token_urlsafe(32))"
SINGLE_USER_API_KEY in .env and restart.
6. "Invalid credentials" after password change¶
Symptoms: Login worked before, now returns 401.
Fix:
1. If you changed SINGLE_USER_API_KEY, you must update any clients, scripts, or browser extensions using the old key.
2. For multi-user mode, verify the user account exists: check the users database or re-run the AuthNZ initializer.
Chat and LLM Issues¶
7. "No LLM provider configured" / amber banner in WebUI¶
Symptoms: Chat page shows a warning banner. API returns 503 with "no provider configured".
Fix:
1. Add at least one provider API key to tldw_Server_API/Config_Files/.env:
OPENAI_API_KEY=sk-...
curl http://localhost:8000/api/v1/llm/providers -H "X-API-Key: YOUR_KEY"
8. Chat request returns 502 or "provider error"¶
Symptoms: Message sent but response is a 502 with details about the upstream provider.
Fix: 1. Verify your API key is valid with the provider directly:
curl https://api.openai.com/v1/models -H "Authorization: Bearer sk-..."
9. Chat returns 429 "rate limit exceeded"¶
Symptoms: Requests work initially but fail with 429 after several calls.
Fix:
1. This is typically the upstream provider's rate limit, not tldw_server's.
2. Reduce request frequency or upgrade your provider plan.
3. If using the built-in rate limiter, check config.txt for rate limit settings.
10. Streaming responses cut off or hang¶
Symptoms: Chat stream starts but stops mid-response or never completes.
Fix:
1. Check server logs for timeout or connection-reset errors.
2. If behind a reverse proxy (nginx, Caddy), ensure it supports SSE and has adequate timeout settings (e.g., proxy_read_timeout 300s in nginx).
3. Try a non-streaming request to isolate: set "stream": false in the request body.
Media Ingestion Issues¶
11. "FFmpeg not found"¶
Symptoms: Video or audio upload fails. Logs show ffmpeg: command not found or the /health endpoint reports ffmpeg_available: false.
Fix:
- macOS: brew install ffmpeg
- Ubuntu/Debian: sudo apt update && sudo apt install -y ffmpeg
- Fedora/RHEL: sudo dnf install -y ffmpeg (RPM Fusion may be required)
- Docker: FFmpeg is included in the official images; rebuild if using a custom image.
Verify: ffmpeg -version
12. YouTube download fails ("yt-dlp error")¶
Symptoms: URL ingestion returns an error mentioning yt-dlp, HTTP 403, or "format not available".
Fix:
1. Update yt-dlp to the latest version: pip install -U yt-dlp
2. Some sites require cookies. If authentication is needed, configure yt-dlp cookies.
3. Check if the URL is accessible: yt-dlp --simulate "YOUR_URL"
13. Upload fails or times out for large files¶
Symptoms: Upload hangs, browser times out, or server returns a 413/timeout.
Fix:
1. Check max_video_file_size_mb in tldw_Server_API/Config_Files/config.txt (default varies by deployment).
2. If behind a reverse proxy, increase client body size limits (e.g., nginx client_max_body_size 2G;).
3. For very large files, consider local ingestion via the API rather than browser upload.
14. PDF ingestion returns empty or garbled text¶
Symptoms: PDF is accepted but extracted text is missing or corrupted.
Fix:
1. The PDF may be image-based (scanned). tldw_server uses text extraction by default; OCR requires additional setup.
2. Try a different PDF: curl -X POST .../api/v1/media/process -F "file=@test.pdf" to isolate the issue.
3. Check if pymupdf is installed: python -c "import fitz; print(fitz.version)".
Transcription and Audio Issues¶
15. "Transcription takes too long"¶
Symptoms: Audio processing runs for many minutes on moderate-length files.
Fix:
1. Use a smaller/faster model (e.g., tiny.en or base.en instead of large-v3).
2. If you have an NVIDIA GPU, enable CUDA acceleration (see GPU Audio Setup).
3. For long files, the system chunks automatically, but total wall time scales with file length.
16. CUDA / torch mismatch¶
Symptoms: RuntimeError: CUDA error or torch not compiled with CUDA or cudnn*.dll not found.
Fix:
1. Verify CUDA is available: python -c "import torch; print(torch.cuda.is_available())"
2. If False, install the CUDA-compatible PyTorch:
pip install torch --index-url https://download.pytorch.org/whl/cu121
cudnn DLLs are on your PATH. See the NVIDIA cuDNN docs.
17. "Numpy is not available" error¶
Symptoms: Runtime error about numpy during transcription model loading.
Fix: Pin numpy to a compatible version:
pip install "numpy<2"
Docker Issues¶
18. Container keeps restarting¶
Symptoms: docker compose ps shows the container in a restart loop.
Fix:
1. Check logs: docker compose logs app --tail 100
2. Common causes:
- Missing MCP secrets: Set MCP_JWT_SECRET and MCP_API_KEY_SALT in .env (or let the Docker entrypoint auto-generate them).
- Bad DATABASE_URL: Verify the Postgres host is reachable from within Docker (use postgres as hostname, not localhost).
- Port conflict: Another service is bound to port 8000 on the host.
19. "Permission denied" on database files¶
Symptoms: Logs show PermissionError or sqlite3.OperationalError: unable to open database file.
Fix:
1. Ensure the Databases/ directory is writable: chmod -R 755 Databases/
2. In Docker, check volume mount ownership. Add user: "1000:1000" in the compose file passed with -f for your stack, such as Dockerfiles/docker-compose.yml, or in your own root-level docker-compose.yml if you maintain one.
20. Docker build fails on chromadb¶
Symptoms: pip install chromadb fails during image build with compilation errors.
Fix:
1. Ensure the base image has build essentials: apt-get install -y build-essential.
2. If on ARM (Apple Silicon), ensure you are building for the correct platform or using a pre-built wheel.
3. See chromadb issue #189 for known workarounds.
21. "make: command not found" on Windows¶
Symptoms: make quickstart fails on Windows.
Fix: Use WSL2 for the documented Makefile path, or run the PowerShell/no-make setup from the profile guide. For Docker single-user + WebUI, the current direct compose command is:
if (!(Test-Path "tldw_Server_API/Config_Files/.env")) { Copy-Item "tldw_Server_API/Config_Files/.env.example" "tldw_Server_API/Config_Files/.env" }
py -m venv .setup-venv
.\.setup-venv\Scripts\python -m pip install --upgrade pip setuptools wheel
.\.setup-venv\Scripts\python -m pip install "typer>=0.12.0" "loguru>=0.7.0" "httpx>=0.24.0" "python-dotenv>=1.0.0" "cryptography>=41.0.0"
.\.setup-venv\Scripts\python -m tldw_Server_API.cli.wizard.cli init --profile docker-single-webui --env-file tldw_Server_API/Config_Files/.env --default --yes
docker compose --env-file tldw_Server_API/Config_Files/.env -f Dockerfiles/docker-compose.single-user.yml -f Dockerfiles/docker-compose.webui.yml up -d --wait
Database Issues¶
22. "database is locked" (SQLite)¶
Symptoms: sqlite3.OperationalError: database is locked under concurrent use.
Fix:
1. SQLite is best for single-user or low-concurrency setups. For multi-user deployments, switch to PostgreSQL.
2. Ensure WAL mode is enabled (it is by default). Check sqlite_wal_mode = true in config.txt under [Database].
3. Keep database transactions short-lived; avoid long-running reads that block writers.
23. Database migration errors on startup¶
Symptoms: Server crashes with schema mismatch or missing column errors.
Fix:
1. Back up your databases first: cp -r Databases/ Databases_backup/
2. Re-run the server; migrations typically auto-apply on startup.
3. If migrations fail, check logs for the specific migration step that errored. Some schema changes require a fresh database (rare).
24. "user_databases" directory missing¶
Symptoms: Content operations fail with file-not-found errors referencing Databases/user_databases/.
Fix: Create the directory:
mkdir -p Databases/user_databases
Multi-User and JWT Issues¶
25. Locked out with no admin account¶
Symptoms: Switched to AUTH_MODE=multi_user but cannot log in.
Fix:
1. Run the create_admin CLI to create (or reset) the admin user:
python -m tldw_Server_API.app.core.AuthNZ.create_admin --username tldw-admin --password "YOUR_NEW_PASSWORD"
docker compose exec app python -m tldw_Server_API.app.core.AuthNZ.create_admin \
--username tldw-admin --password "YOUR_NEW_PASSWORD"
26. JWT tokens rejected after server restart¶
Symptoms: Previously valid tokens return 401 after restarting.
Fix:
1. Ensure JWT_SECRET_KEY is set explicitly in .env (not auto-generated on each boot).
2. Generate a persistent key:
python -c "import secrets; print(secrets.token_urlsafe(32))"
.env as JWT_SECRET_KEY=... and restart.
27. "DATABASE_URL" points to wrong database in multi-user mode¶
Symptoms: Auth works in single-user but breaks when switching to multi-user.
Fix:
1. Multi-user mode requires a users.db (SQLite) or a PostgreSQL connection.
2. Verify DATABASE_URL in .env:
- SQLite: sqlite:///./Databases/users.db
- Postgres: postgresql://user:pass@host:5432/dbname
3. Ensure the database file or Postgres instance is accessible.
CORS and Browser Issues¶
28. "Cross-origin request blocked" in browser console¶
Symptoms: API calls from the WebUI fail; browser DevTools shows a CORS error.
Fix:
1. Set ALLOWED_ORIGINS in .env to include your WebUI origin:
ALLOWED_ORIGINS=http://localhost:3000,http://localhost:8080
DISABLE_CORS=true
29. "ALLOWED_ORIGINS is empty" crash on startup¶
Symptoms: Server refuses to start with CORS is enabled but ALLOWED_ORIGINS is empty.
Fix:
1. Add at least one origin to .env:
ALLOWED_ORIGINS=http://localhost:3000
ALLOWED_ORIGINS=* with CORS_ALLOW_CREDENTIALS=false.
3. In production, always list explicit origins.
30. CORS credentials conflict¶
Symptoms: Startup error: ALLOWED_ORIGINS cannot include '*' when credentials are enabled.
Fix: You cannot use ALLOWED_ORIGINS=* together with CORS_ALLOW_CREDENTIALS=true. Either:
- List specific origins instead of *, or
- Set CORS_ALLOW_CREDENTIALS=false.
Embedding and RAG Issues¶
31. "Embedding model not found" or slow first query¶
Symptoms: First RAG or embedding request takes a long time or fails with a download error.
Fix:
1. The default embedding model downloads on first use. Ensure internet access is available.
2. Check the model directory path in config.txt under model_dir.
3. If behind a corporate proxy, set HTTP_PROXY/HTTPS_PROXY environment variables.
32. ChromaDB collection errors¶
Symptoms: Errors about missing collections, dimension mismatch, or ChromaDB startup failures.
Fix:
1. Verify the ChromaDB path in config.txt (chroma_db_path = Databases/chroma_db).
2. A dimension mismatch means you changed the embedding model after initial indexing. Re-index or delete the old ChromaDB directory:
rm -rf Databases/chroma_db
MCP Issues¶
33. MCP secrets missing or placeholder¶
Symptoms: Server fails on startup with errors about MCP_JWT_SECRET or MCP_API_KEY_SALT.
Fix:
1. Docker users: the entrypoint auto-generates these if they are set to placeholder values. Rebuild: docker compose up -d --build.
2. Non-Docker users: generate and set them manually in .env:
python -c "import secrets; print(secrets.token_urlsafe(32))"
# Set output as MCP_JWT_SECRET=... and MCP_API_KEY_SALT=...
34. MCP WebSocket connection rejected¶
Symptoms: WebSocket clients cannot connect to MCP endpoints.
Fix:
1. Check MCP_WS_AUTH_REQUIRED in .env (default: true). Ensure your client sends valid auth.
2. Verify MCP_WS_ALLOWED_ORIGINS includes your client's origin.
3. If behind a reverse proxy, ensure it supports WebSocket upgrade headers.
WebUI Issues¶
35. WebUI login page loops or shows "session expired"¶
Symptoms: Logging in redirects back to the login page.
Fix:
1. Clear browser cookies and local storage for the site.
2. Verify that JWT_SECRET_KEY has not changed between server restarts (see issue #26).
3. Check browser DevTools Network tab for the specific error on the auth endpoint.
36. "NEXT_PUBLIC_X_API_KEY" confusion¶
Symptoms: Frontend admin features do not work, or you get 401 errors only from the WebUI.
Fix:
Docker single-user WebUI quickstart uses runtime auth bootstrap. Check these when the WebUI returns 401:
make setup-docker-singleor the equivalenttldw-setup init --profile docker-single-webuicommand wroteTLDW_WEBUI_EXPOSE_RUNTIME_AUTH=1totldw_Server_API/Config_Files/.env; the shared WebUI compose overlay defaults that flag to0without this explicit local quickstart opt-in.- The WebUI is opened through the default loopback URL,
http://127.0.0.1:8080. SINGLE_USER_API_KEYis notchange-me.- The backend
appservice has the sameSINGLE_USER_API_KEY.
NEXT_PUBLIC_X_API_KEY is a browser-visible copy of the single-user API key. Only advanced/static local single-user deployments should set it before building the WebUI. In a separate local WebUI dev server, set it only if you want automatic single-user auth. Do not set it for multi-user/JWT deployments, shared production deployments, or any browser bundle where exposing the single-user API key is unacceptable. If you intentionally change it for a built WebUI image, rebuild the WebUI so the public build-time value changes.
Performance Issues¶
37. Slow API response times¶
Symptoms: Requests take several seconds even for simple queries.
Fix: 1. If using a remote LLM provider (OpenAI, Anthropic, etc.), latency is dominated by the provider round-trip; this is expected. 2. For faster responses, consider a local model (Ollama, llama.cpp, vLLM). 3. Check if embedding model downloads or ChromaDB initialization are happening on-demand.
38. High memory usage¶
Symptoms: Server process consumes multiple GB of RAM, system becomes sluggish.
Fix:
1. Local STT models (especially large-v3) require significant memory. Use a smaller model (tiny.en, base.en).
2. Reduce concurrent ingestion tasks.
3. If embedding models are loaded locally, they consume RAM proportional to model size. Consider using an API-based embedding provider.
39. Redis connection errors (optional component)¶
Symptoms: Logs show Redis connection failures or REDIS_URL errors.
Fix:
1. Redis is optional. If you are not using it, ensure REDIS_URL is not set or is empty in .env.
2. If you want Redis, verify it is running and accessible at the configured URL.
3. Check docker compose ps to ensure the Redis container is healthy.
Installation Issues¶
40. ModuleNotFoundError on startup¶
Symptoms: ModuleNotFoundError: No module named 'loguru' (or similar).
Fix:
1. Activate your virtual environment: source .venv/bin/activate
2. Install dependencies: pip install -e . or pip install -e ".[dev]"
3. If using Docker, rebuild: docker compose build --no-cache
41. Python version too old¶
Symptoms: SyntaxError or ImportError on startup due to Python 3.9 or earlier features.
Fix: tldw_server requires Python 3.10+. Check your version:
python3 --version
make quickstart-install PYTHON=python3.12
42. pip install fails on platform-specific packages¶
Symptoms: Build errors for packages like chromadb, hnswlib, or faster-whisper during install.
Fix:
1. Ensure build tools are installed:
- macOS: xcode-select --install
- Ubuntu/Debian: sudo apt install build-essential python3-dev
2. For Apple Silicon, ensure you are using an ARM-native Python (not Rosetta).
3. If a specific package fails, check its GitHub issues for platform-specific workarounds.
Still Stuck?¶
If your issue is not listed here:
- Check the logs. Server logs contain detailed error messages and stack traces. Look for the first error after startup.
- Search GitHub Issues. Your problem may already be reported: github.com/rmusser01/tldw_server/issues
- Ask in Discussions. The community forum is a good place for questions: github.com/rmusser01/tldw_server/discussions
- File a bug. Include your OS, Python version, deployment method (Docker/local), and the full error message.