Self-hosting
Troubleshooting
Start with readiness and logs, then isolate webhook, queue, AI, REES, RAG, or write-suppression problems.
First checks
docker compose ps
docker compose logs --tail=200 gittensory
curl http://localhost:8787/ready
curl http://localhost:8787/metricsbashNo review appears
- Webhook
- Check GitHub App deliveries and confirm /v1/github/webhook receives 2xx responses.
- Allowlist
- Confirm the repo is in GITTENSORY_REVIEW_REPOS for per-PR features.
- Write mode
- SELFHOST_DEPLOYMENT_MODE=dry-run or disabled suppresses writes even when review computes.
- Policy
- gate.aiReview.mode=off or commentMode=off can make AI/comment output intentionally quiet.
AI summary unavailable
- Confirm
AI_PROVIDERis set and supported. - Confirm the provider key or local endpoint works from inside the container.
- Set the matching provider model env, such as
ANTHROPIC_AI_MODEL,OPENAI_COMPATIBLE_AI_MODEL,OLLAMA_AI_MODEL,CLAUDE_AI_MODEL, orCODEX_AI_MODEL. - Increase the matching provider timeout env, such as
CLAUDE_AI_TIMEOUT_MSorCODEX_AI_TIMEOUT_MS, for large subscription-CLI reviews. - For CLI providers, confirm the CLI binary and credential path are available.
REES is silent
A no-finding REES response can be intentionally invisible. For failures, search logs forreview_context_fetch_failed with contextType set to enrichment.
review_context_fetch_failed
rees_analyzer_config_invalidCheck REES enrichment for enablement and REES analyzer reference for analyzer names, network calls, and token requirements.
RAG returns no context
- Confirm
GITTENSORY_REVIEW_RAG=trueand repo activation. - Confirm Qdrant or the vector backend is reachable from the app container.
- Confirm the embedding endpoint and model are running.
- Confirm the repo has been indexed after enabling the feature.
Queue stuck or dead jobs
Watch pending, processed, failed, and dead metrics. A high pending count can be webhook replay or maintenance work; dead jobs need direct investigation.
curl http://localhost:8787/metrics | grep gittensory_queue
docker compose logs gittensory | grep selfhost_job_deadbashGrafana traces error or show no data
The trace path is app or smoke process → OTEL collector → Tempo → Grafana. Tempo is only started by the observability profile, and app traces are only emitted when OTEL_TRACES_EXPORTER includes otlp.
docker compose --profile observability ps tempo otel-collector grafana
docker compose logs --tail=80 tempo otel-collector grafana
# Send one synthetic span through the collector and read it back from Tempo.
npm run test:smoke:observabilitybash- If the smoke command fails at
otel-collector:4318/v1/traces, the collector is not reachable from the app container. - If it pushes successfully but cannot read
tempo:3200/api/traces/<trace_id>, Tempo is unhealthy, not ingesting, or not sharing the Compose network. - If the smoke command passes but Grafana Explore fails, check the Tempo data source URL. It should point at
http://tempo:3200, not the OTLP ingest ports. - For a temporary live debugging run, set
OTEL_TRACES_SAMPLER_ARG=1so every root trace is sampled, then lower it again after diagnosis.
Readiness fails
- DB
- Check DATABASE_URL or DATABASE_PATH, volume permissions, Postgres reachability, and migrations.
- Migrations
- Read startup logs for migration errors before recreating volumes.
- Dependencies
- If Qdrant or Postgres profiles are enabled, confirm those services are healthy first.