How to Troubleshoot Open-Notebook: FastAPI, SurrealDB, and Frontend Diagnostics
TLDR: Open Notebook is a three-tier application (frontend → FastAPI → SurrealDB), and nearly every failure can be isolated by checking container logs, verifying environment variables like OPEN_NOTEBOOK_ENCRYPTION_KEY and CORS_ORIGINS, and confirming that database migrations completed successfully.
Troubleshooting lfnovo/open-notebook starts with its architecture. The stack runs as three distinct layers—frontend interface, FastAPI backend, and SurrealDB datastore—so every symptom points to a specific tier. By tracing failures through the source code paths below, you can diagnose and resolve most issues without guessing.
Troubleshoot Open-Notebook API Startup and Migration Failures
When the API container launches, the lifespan handler in api/main.py (lines 98–127) orchestrates startup. It first validates that OPEN_NOTEBOOK_ENCRYPTION_KEY is defined, logging a critical warning if the variable is missing. Then it delegates to AsyncMigrationManager from open_notebook/database/async_migrate.py to run pending SurrealDB migrations; if these fail, the service aborts entirely.
The most common startup symptom is a log line reading "CRITICAL: Database migration failed". To fix this, inspect the container output with docker logs open_notebook and verify that SurrealDB is reachable on port 8000 via telnet <host> 8000. If the database version has drifted, run docker exec -it surrealdb /surreal version and compare it with the API log entry showing Current database version:.
A missing encryption key triggers subtle failures later. You must export a secret before starting the stack, as shown in the sample docker-compose.yml (lines 31–33) and the README.md (lines 44–49):
export OPEN_NOTEBOOK_ENCRYPTION_KEY=$(openssl rand -hex 32)
If migrations are stuck in an inconsistent state, delete the surreal_data Docker volume and restart the compose stack so SurrealDB initializes a fresh datastore.
Fix CORS Misconfiguration in Open-Notebook
The API parses CORS_ORIGINS at startup inside api/main.py (lines 53–64). If the variable is absent, the backend defaults to * and logs a warning, which causes browsers to reject cross-origin requests whenever credentials are sent.
Symptoms include a blank UI and "Failed to fetch" errors in the browser console. Inspect the response headers with a quick curl command:
curl -I http://localhost:5055/api/health
If Access-Control-Allow-Origin is missing or set to * while your frontend sends cookies, explicitly set the exact frontend URL in your environment:
CORS_ORIGINS=https://localhost:8502
After updating .env or docker-compose.yml, restart the API container so the new CORS policy takes effect.
Resolve Authentication and Encryption Key Errors in Open-Notebook
PasswordAuthMiddleware protects all routes except an explicit whitelist, as configured in api/main.py (lines 73–86). This middleware relies on the same OPEN_NOTEBOOK_ENCRYPTION_KEY used during startup; if the key is absent or differs between containers, every protected endpoint returns 401 Unauthorized.
Symptoms include repeated login loops and a "Login required" overlay even after entering valid credentials. Ensure the secret is identical in both the API container and the frontend runtime, because the frontend retrieves it from /api/config to validate password hashes. Any mismatch prevents decryption and blocks access.
Handle Podcast Profile Migration Warnings
During startup, a legacy migration routine runs inside api/main.py (lines 39–46). Errors here are logged but do not stop the service, so you may see warnings such as "Podcast profile migration encountered errors" while the API remains online.
If old profile strings were not converted automatically, open the notebook UI and navigate to Settings → Podcast Profiles, then click Migrate Profiles. The UI invokes the migration endpoint again and completes the conversion interactively.
Diagnose Open-Notebook Frontend Connection Errors
The UI surfaces generic failures through ConnectionErrorOverlay.tsx (line 59), pulling text from the locale file frontend/src/lib/locales/en-US/index.ts (line 174). This overlay usually appears when the frontend cannot reach the API, but the root cause can sit at multiple network layers.
-
API URL mismatch. The frontend base URL is defined in
.env.localand expects the API athttp://localhost:5055by default. If you changed ports or hostnames, propagate that value into the build. -
Reverse-proxy header stripping. If you run nginx or Traefik in front of the stack, confirm it forwards the
HostandOriginheaders and preserves CORS headers on error responses. The project documentation indocs/5-CONFIGURATION/reverse-proxy.mdcovers recommended proxy settings. -
Docker network isolation. Run
docker network inspect <network>and verify that both theopen_notebookandsurrealdbservices attach to the same bridge.
Run these quick tests from the host and from inside the frontend container:
# From the host
curl http://localhost:5055/api/health
# From inside the frontend container
docker exec -it open_notebook_frontend curl http://open_notebook:5055/api/health
Both calls must return {"status":"healthy"}.
Fix AI Provider and Model Timeouts in Open-Notebook
Open Notebook uses the Esperanto library for multi-provider AI. Provider-specific failures surface as ExternalServiceError, handled in api/main.py (lines 71–78). You will typically see "No models available" or "Failed to send message" in the chat UI.
Start by verifying the credential record exists through api/routers/credentials.py. In the UI, go to Settings → API Keys → Test Connection to confirm the key is active. If the request times out, test outbound network access from the container:
docker exec open_notebook ping api.openai.com
For local Ollama deployments, ensure the model name matches the output of ollama list exactly, as noted in CHANGELOG.md (lines 260–261). If you are using the Google provider and Docker cannot resolve the host, add extra_hosts to your compose service as described in docs/5-CONFIGURATION/ollama.md (line 330).
Quick Diagnostic Scripts for Open-Notebook
The repository ships a rapid troubleshooting guide in docs/6-TROUBLESHOOTING/quick-fixes.md. Use the following scripts to automate common checks.
Bash health-check script
Save the following to health_check.sh and run it to verify API and database reachability:
#!/usr/bin/env bash
set -e
if curl -sSf http://localhost:5055/api/health | grep -q "healthy"; then
echo "✅ API healthy"
else
echo "❌ API not responding"
exit 1
fi
if nc -zv localhost 8000 2>/dev/null; then
echo "✅ SurrealDB reachable"
else
echo "❌ SurrealDB not reachable"
fi
Inspect CORS headers with Python
Use this snippet to read the Access-Control-Allow-Origin header returned by the API:
import requests
resp = requests.get("http://localhost:5055/api/health")
print("CORS header:", resp.headers.get("Access-Control-Allow-Origin"))
Trigger a migration manually
If the API fails to start because of a migration error, you can run the manager directly:
import asyncio
from open_notebook.database.async_migrate import AsyncMigrationManager
async def run():
mgr = AsyncMigrationManager()
await mgr.run_migration_up()
print("Migrations applied")
asyncio.run(run())
Test AI credentials via cURL
Send a direct request to the credentials router to validate an API key:
curl -X POST http://localhost:5055/api/credentials/test \
-H "Content-Type: application/json" \
-d '{"provider":"openai","api_key":"sk-..."}'
A successful response contains "status":"ok".
Summary
- Check container logs first. Run
docker logs open_notebookanddocker compose psto confirm every service is healthy. - Validate environment variables.
OPEN_NOTEBOOK_ENCRYPTION_KEYandCORS_ORIGINSare the most common sources of silent failures and 401 errors. - Confirm database reachability. Use
telnetorncagainst SurrealDB port8000, and match the reported database version with the API logs. - Inspect CORS headers. Browsers block requests when
Access-Control-Allow-Originis*while credentials are enabled. - Test AI providers from the UI. Use Settings → API Keys → Test Connection before assuming a model outage.
- Delete and recreate the
surreal_datavolume only when migrations are irreparably stuck, since this wipes the datastore.
Frequently Asked Questions
Why does the Open Notebook API container exit immediately on startup?
The lifespan handler in api/main.py (lines 98–127) aborts the process when AsyncMigrationManager cannot apply pending SurrealDB migrations. Check docker logs open_notebook for the exact migration error, verify SurrealDB is reachable on port 8000, and ensure OPEN_NOTEBOOK_ENCRYPTION_KEY is exported in your environment.
Why am I getting 401 Unauthorized even after logging in?
PasswordAuthMiddleware—configured in api/main.py (lines 73–86)—requires the exact same OPEN_NOTEBOOK_ENCRYPTION_KEY on both the API and frontend to decrypt password hashes. If the keys differ, every protected route returns 401. Synchronize the secret across both containers and restart them.
Why does the frontend show a "Connection error" overlay?
The overlay defined in frontend/src/components/errors/ConnectionErrorOverlay.tsx (line 59) appears when the UI cannot fetch from the API. Confirm the frontend is pointing to the correct API URL, run curl http://localhost:5055/api/health from both the host and inside the frontend container, and verify that any reverse proxy preserves Host and Origin headers.
How do I fix AI provider errors like "No models available"?
These are thrown as ExternalServiceError in api/main.py (lines 71–78). Verify your provider credentials in api/routers/credentials.py, run the test connection button in Settings → API Keys, and check container outbound access with docker exec open_notebook ping api.openai.com. For Ollama users, confirm the model name matches ollama list exactly, and for Google provider timeouts add extra_hosts as documented in docs/5-CONFIGURATION/ollama.md (line 330).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →