Where to find the logs, and how to fix the problems Kribble servers commonly run into
Start with the logs. Most problems leave a clear message there. The sections below are grouped by symptom and quote the messages to look for.
journalctl -u kribble-web -f
journalctl -u kribble-builder -f
journalctl -u kribble-web --since "1 hour ago" | grep '"level":"error"'
journalctl -u meilisearch -n 50
docker compose logs -f kribble-web
docker compose logs -f kribble-builder
docker compose logs --tail 50 meilisearch db
In prod mode, Kribble logs one JSON object per line on standard output, at level info. For more detail, set LOG_LEVEL=debug in a unit drop-in (sudo systemctl edit kribble-web, then Environment=LOG_LEVEL=debug) and restart. LOG_FORMAT=console makes the log easier to read by eye. LOG_DIR also writes the log to rotated files (Configuration).
Health checks:
curl -i http://127.0.0.1:8080/healthz # kribble-web is up
curl -i http://127.0.0.1:8080/readyz # 503 while it shuts down
curl -i http://127.0.0.1:8081/healthz # kribble-builder is up
curl -s http://127.0.0.1:8080/api/v1/config
curl -s http://127.0.0.1:7700/health # Meilisearch
A healthy start logs Connected to database postgres and Kribble web server starting on :8080 from kribble-web, and Kribble builder running (workers=2, health :8081) and build queue: started from kribble-builder. The System tab of the admin panel shows the number of builds waiting and whether Redis and Meilisearch are configured.
Message | Cause and fix |
|---|---|
| No config file at |
| TOML syntax error; the message gives the line. |
| Fix the value. |
| Complete the target or rename it (Publish targets). |
| Set |
| PostgreSQL is unreachable, the password is wrong, or the user doesn't own the database. Test the DSN with |
|
|
| Set |
| The storage directory is outside |
|
|
| Complete the |
| Something else uses |
systemd restarts a service that exits with an error every 5 seconds, so the same message repeats until you fix it.
Signed out again right after signing in, or after a reload. The session cookie is marked Secure, so browsers drop it on plain HTTP. Open the server through its HTTPS address. On an internal test machine without TLS you can use mode = "dev", never on a real server.
429 Too Many Requests when signing in. Sign-in allows 10 requests a minute per client address. If the reverse proxy doesn't send X-Forwarded-For, every user shares the proxy's address and the limit is reached quickly. Fix the proxy (Installing). After several wrong passwords, a single person also has to wait up to 16 seconds between attempts.
Locked out of the admin panel. Add your email to [admin].emails and restart kribble-web. If the log says admin: email listed in admin_emails but no user row yet, the account with that email doesn't exist.
Someone forgot their password and email isn't configured. There is no password reset in the admin panel. Configure email (Authentication), restart, and have them use Forgot password on the sign-in page.
At startup kribble-web logs [email] provider=… from=…. With provider=none, nothing is sent and each email is only logged as [email] (no provider) would send to=… subject=…. Set [email].provider and its settings.
[email] failed to send to <address> gives the transport's error:
smtp auth: … unencrypted connection: Kribble won't send the SMTP password without TLS, except to localhost. Use port 587 (STARTTLS) or 465 (TLS), or set encryption.
smtp dial: … certificate …: the SMTP server's certificate doesn't match host or isn't trusted.
Errors from Resend usually mean the from domain isn't verified there.
Links in emails pointing to localhost:5173 mean [server].frontend_url isn't set.
Mail that is sent but lands in spam needs SPF and DKIM for the from domain. That is set up at your mail provider.
Check the Auth Sources tab of the admin panel to see what Kribble loaded, and LDAP: enabled sources=… at startup. Then look for these messages after a failed login:
Message | Meaning |
|---|---|
No LDAP message, login fails | No enabled source found the user. Check |
|
|
… with | The server is unreachable, or TLS fails (certificate not trusted by the host). |
… with | The filter matches several entries. Make it stricter. |
| All sources failed with a directory error, so the local password was tried. |
| The entry has no value for |
| Login worked, but the group search failed. Check |
A wrong password gives the normal "invalid identifier or password" error and no LDAP log line. If group sync adds nobody, check that the organisation and teams in [[ldap.team_map]] exist with exactly those names, and that group_dn matches the DN the directory returns. The ldap sync: lines at info level show who was added where.
Saving a note doesn't depend on Meilisearch. The note is saved first and added to the search index afterwards, and if that fails, Kribble logs search: failed to index notes and the save still succeeds. So while Meilisearch is down, people can work as usual, but:
full-text search fails: the search box in the app still finds note titles, and the CLI, the desktop app's search and agents get an error
notes changed in the meantime are missing from search, or found by their old text, until they are saved again or the index is rebuilt
To fix it:
Check Meilisearch: curl http://127.0.0.1:7700/health (or docker compose logs meilisearch). In production mode Meilisearch needs a master key of at least 16 bytes and refuses to start without one.
Check that [meili].host and [meili].key match the running Meilisearch. A wrong key gives authorization errors in the log.
When kribble-web starts, it applies the index settings that search relies on, in the background. If Meilisearch isn't reachable, it logs search: index setup failed; search may be degraded and tries again, waiting longer each time, from 5 seconds up to 5 minutes. It keeps trying until Meilisearch answers, so nothing needs restarting.
If Meilisearch was down or unreachable while notes changed, rebuild the index: click Rebuild index under Search on the System tab of the admin panel (Instance admin in the user menu), or, as an instance admin, POST /api/v1/admin/search/reindex. The rebuild runs in the background, and search keeps working meanwhile. The log shows search: index rebuilt with the number of notes and the time it took, or admin: search reindex failed.
If Meilisearch lost its data, for example a deleted volume or a new installation, click Rebuild index (or restart kribble-web, which finds the index empty and rebuilds it, logging search: rebuilding the index). Either way the index and its settings are set up again before the notes are written.
Search results are checked against the database before they are shown, so a note that was deleted, or moved to a space the person can't open, never appears, even when the index is behind.
Symptom | Fix |
|---|---|
| Install Chromium or Chrome on the |
| Chromium started but failed. Run the binary by hand as the |
Text in a template prints in another font than in the PDF designer | Serif (system) and Sans (system) use the serif and sans-serif fonts installed on the |
| A render can take up to 90 seconds. Raise the proxy's read timeout (nginx |
Exporting PDFs covers templates and the export itself.
Stuck at queued. The builder isn't running, or can't reach the database. Check systemctl status kribble-builder (or docker compose ps) and its log. The System tab's Build queue counts sites queued or building. A running builder picks up queued sites within 10 seconds.
Stuck at building. The builder was stopped mid-build. It puts the site back in the queue when it starts again. After 3 attempts the builder marks the site failed on its next start instead of trying again.
failed. The site couldn't be generated. The builder logs build queue: build failed with the site's ID and the error, or build queue: marked poison builds as failed for the attempt limit. Fix the cause and publish or kribble redeploy again; that resets the attempts.
publish_failed. The site was built but couldn't be copied to its external target. The publish dialog and kribble sites show the error, and the builder logs external publish failed. Common errors:
Error | Fix |
|---|---|
| Allow |
| Fill |
| Set |
| The key must be readable by |
| The public key isn't in the remote user's |
| The target was renamed or removed. Put it back, or unpublish the site and publish it to another target. |
Cloudflare errors with | The API token lacks Cloudflare Pages edit permission for |
| A file in the site is over 25 MiB. Remove or shrink it. |
Public site without images, icons or styles. [storage.s3].public_bucket_url doesn't point at https://<server>/files-public. Fix it and rebuild the site.
Site links reported by the CLI point to localhost. Set [server].frontend_url.
Uploads over 1 MB fail with 413. nginx's default client_max_body_size is 1 MB. Set it to 500m.
Large attachments don't download with the S3 backend. Files over proxy_threshold_bytes (15 MiB) are sent as a redirect to a presigned S3 URL, so the browser must reach [storage.s3].endpoint. An endpoint only reachable inside your network (such as an internal MinIO address) breaks this. Use an endpoint browsers can reach, or raise proxy_threshold_bytes so files stream through Kribble.
Start with kribble status: it shows the profile, server, account and both versions, and whether the token still works.
Message | Fix |
|---|---|
| Wrong address, DNS, TLS or proxy. Try |
| The token was revoked, expired, or its creator was removed from the organisation. Sign in again. |
| The token lacks the scope. Tokens from |
| MCP doesn't accept browser sessions. Use |
| Run |
| The server has no |
The install command shows | The proxy doesn't pass |
More on the CLI side is in The kribble CLI and AI agents.