Skip to main content
If your issue isn’t listed here, open an issue at github.com/yourhq/yourhq/issues with the exact error text, your host OS, and the output of docker compose logs for the failing service.

UI & access

What you seeYou open http://localhost:3000 and get sent back to onboarding even though you already connected Supabase.Why it happensThe UI reads Supabase config from the workspace registry stored in the ui-config Docker volume. The registry is empty, unreadable, or was cleared when volumes were recreated.FixCheck the UI logs first:
cd ~/.yourhq
docker compose logs ui
Then either complete onboarding again (paste your Supabase URL and keys) or inspect the ui-config volume. If you intentionally reset volumes, this is expected. Supabase config is runtime-injected — rebuilding the UI image is not required.
What you seeYou type your email/password, click Sign in — nothing happens, or you see Invalid API key / Invalid login credentials.Why it happensEither (a) the anon key in the UI doesn’t match the Supabase project you’re pointing at, or (b) you never created an auth user in Supabase. A fresh Supabase project has zero users.Fix
  1. In Supabase → Project Settings → API, confirm Project URL and anon public match what you entered in HQ Settings → Database.
  2. In Supabase → Authentication → Users → Add user → Create new user, create an email + password. Check Auto Confirm User.
  3. Log in with those credentials.
What you seeYou’re going through the onboarding wizard and a step fails with a 500 error. docker compose logs ui shows Origin mismatch or CSRF error.Why it happensNext.js server actions enforce that the Origin header matches the host. When you access HQ through a proxy, Tailscale IP, or Codespaces forwarded URL, the origin doesn’t match localhost and the action is rejected.FixSet ALLOWED_ORIGINS in ~/.yourhq/.env to the exact origin you’re loading the UI from:
ALLOWED_ORIGINS=https://<codespace-name>-3000.app.github.dev,http://100.x.y.z:3000
Then restart the UI:
docker compose up -d ui
Codespaces: the installer sets this automatically if CODESPACE_NAME is in the environment. If you’re using a VS Code tunnel, set it manually.
What you seeUI works at http://localhost:3000 on the host but times out from your phone or another laptop at http://100.x.y.z:3000.Why it happensLocal-only installs bind the UI to 127.0.0.1:3000. Docker publishes the port on loopback only — the tailnet can’t reach it.FixEdit ~/.yourhq/.env:
UI_HOST_PORT=0.0.0.0:3000
FILES_API_HOST_PORT=0.0.0.0:18790
HOST_REACHABLE_URL=http://100.x.y.z    # your Tailscale IP
NETWORKING_MODE=tailscale
Recreate containers:
docker compose up -d --force-recreate
See Networking →
What you see
Error response from daemon: pull access denied for ghcr.io/yourhq/yourhq-ui,
repository does not exist or may require 'docker login'
Why it happensDuring early access, the GHCR repo is private. Unauthenticated pulls are denied.FixCreate a GitHub PAT with read:packages scope, then log in:
echo "<your-PAT>" | docker login ghcr.io -u <your-github-username> --password-stdin
docker compose pull
docker compose up -d
Alternatively, build locally (needs more RAM — see the t3.medium issue below):
docker compose build
docker compose up -d

Gateway & containers

What you see
$ docker compose ps
NAME               STATUS
yourhq-gateway     Restarting (1) 8 seconds ago
Why it happensThe gateway entrypoint chains several steps: openclaw onboard, Xtigervnc, D-Bus, XFCE, websockify. Any step failing exits non-zero and Docker loops.FixTail the logs and find the last step that ran:
docker compose logs --tail=200 gateway
Common culprits:
  • openclaw onboard exits non-zero — usually a bad SUPABASE_SERVICE_ROLE_KEY or Node version mismatch. Check: docker compose exec gateway node --version (must be v24.x). Re-confirm the service role key in Supabase → Settings → API.
  • Xtigervnc won’t start (stale lock files) — clear the state volume: docker compose down && docker volume rm yourhq-gateway-state && docker compose up -d gateway.
  • D-Bus socket never appeared — force recreate: docker compose up -d --force-recreate gateway.
What you seeYou open http://<host>:6901/vnc.html, click Connect — a black viewport with no cursor, no desktop.Why it happensXtigervnc is up, but the XFCE session died. Almost always a D-Bus socket issue — XFCE won’t start xfwm or xfce4-panel without a session bus.FixCheck the logs inside the gateway:
docker compose exec gateway tail -50 /home/openclaw/xfce.log
docker compose exec gateway tail -20 /home/openclaw/dbus.log
Force recreate usually fixes it:
docker compose up -d --force-recreate gateway
If it still fails, clear the state volume (destroys agent workspace and OpenClaw auth — you’ll need to re-OAuth):
docker compose down
docker volume rm yourhq-gateway-state
docker compose up -d
What you see~/.vnc/websockify.log ends with:
[Errno 99] Cannot assign requested address
Why it happensWebsockify is trying to bind to a non-existent interface. Tailscale runs on the host, not inside the container — the gateway only knows 0.0.0.0 and 127.0.0.1.FixEnsure .env has:
NOVNC_BIND=local
NOVNC_BIND=local makes websockify bind to 0.0.0.0:6901 inside the container. Port 6901 is not mapped to the host — the UI proxies noVNC through its own /api/novnc route over Docker’s internal network.Then: docker compose up -d --force-recreate gateway
What you seetailscale status doesn’t show the gateway, or shows an old yourhq-gateway node as inactive.Why it happensTailscale runs on the host, not inside the gateway container. Earlier versions ran it inside the container — those docs are outdated.FixCheck Tailscale on the host:
sudo tailscale status
sudo tailscale ip -4
If missing, re-run the host install:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --authkey=tskey-auth-... --hostname="yourhq-$(hostname)"
Update .env with HOST_REACHABLE_URL=http://<new-ip> and recreate: docker compose up -d --force-recreate.
What you see
Registering gateway default in Supabase ...
  registration failed (Supabase unreachable or gateways table missing — will retry from daemon)
Why it happensEither SUPABASE_SERVICE_ROLE_KEY is wrong, or the gateways table doesn’t exist because migrations were never run.Fix
  1. Copy the service role key again from Supabase → Settings → API → service_role (not the anon key). Update it in HQ Settings → Database or in .env.
  2. Confirm migrations are complete: run every file in db/migrations/ in order from Supabase SQL Editor.
  3. Restart: docker compose restart gateway.
The log should change to registered (reachable at http://...).

Agents

What you seeYou create an agent in the UI. Status shows provisioning and never changes.Why it happensThe provision command is leased by the runner container, which runs add-agent.sh. Something in that script failed — template branch missing, git repo corruption, or a Supabase write blocked by RLS.FixTail the runner:
docker compose logs -f runner
Common causes:
  • fatal: A branch named 'template/cofounder' not foundTEMPLATES_SOURCE pointed at a repo missing that template. Clear the source (TEMPLATES_SOURCE= in .env) and restart the gateway so it uses bundled templates.
  • permission denied writing to /home/openclaw/... — volume owned by wrong UID. docker compose down && docker volume rm yourhq-gateway-state && docker compose up -d.
  • HTTP 401/403 writing to Supabase — service role key wrong. See gateway registration issue above.
If the command is simply stuck with no activity, manually mark it failed to unblock the UI:
-- in Supabase SQL Editor
update agent_commands set status='failed', error='manual cancel'
where status='in_progress' and leased_at < now() - interval '5 minutes';
What you seeYou send a DM to your agent’s Telegram/Discord bot. No reply.Why it happens (Telegram / Discord)99% of the time: you skipped the pairing step. OpenClaw’s default policy is pairing — the bot won’t engage until you pair your account to the agent.Fix (Telegram / Discord)
  1. Send any message to the bot. It should reply with a 6-digit pairing code.
  2. Open the UI → agent detail page → Pairing Code field → paste the code → submit.
  3. Send another message. The agent will respond.
If the bot doesn’t send a pairing code at all, it means the bot token is invalid or add-agent.sh never ran successfully — check runner logs: docker compose logs runner | grep provision.Fix (Slack)
  1. Verify the App-Level Token (xapp-...) has the connections:write scope.
  2. Verify the Bot Token (xoxb-...) has chat:write, im:history, im:read, im:write.
  3. Check runner logs: docker compose logs runner | grep provision.
  4. Check gateway logs: docker compose logs gateway | grep slack.
What you seeYou ask the agent something it should know from a previous conversation — it acts like it has no idea.Why it happensAgent memory lives in files on the git branch (e.g., MEMORY.md). The agent reads and updates these files during sessions. If the state volume was recreated, or the agent’s branch was reset, memory is gone.FixCheck if the agent’s branch exists:
docker compose exec gateway git --git-dir=/home/openclaw/.openclaw/agents/<slug>/.git log --oneline -5
If the branch is missing or corrupt, the agent was re-provisioned from template — it starts fresh. You’ll need to re-share context.To protect against this in the future: set GIT_REMOTE_URL in .env to sync agent branches to GitHub/Gitea. See Operations →
What you seeAutomation rules are set up, inbox items appear in Settings → System → Inbox, but the agent never processes them.Why it happensThe dispatcher checks six conditions before waking an agent. Any one can block it:
ConditionWhat to check
Agent pausedAgent status in UI — must be ready
Budget exceededAgent budget section — hard cutoff may be blocking
Another instance runningCheck for a stuck openclaw process: docker compose exec gateway ps aux | grep openclaw
Cooldown activeInbox items may be rate-limited per agent
Active leaseA command may be leased but stuck — check agent_commands table
Fix
  1. Check agent status: Agents → select agent → status must show ready, not paused.
  2. Check budget: scroll to Usage & Budget — if hard cutoff is hit, raise the limit or wait for next period.
  3. Check dispatcher logs: docker compose logs -f dispatcher
  4. If a command is stuck: mark it failed in Supabase SQL Editor (see provisioning fix above).
See Inbox dispatch reference →
What you seeThe agent responds to messages but doesn’t use its skills — it describes what it would do rather than doing it, or says it can’t find the skill.Why it happensSkills are shell scripts or markdown files on the agent’s git branch under skills/. If the branch wasn’t seeded correctly from the template, the skills directory may be empty or missing.FixInspect the agent’s skills directory:
docker compose exec gateway ls /home/openclaw/.openclaw/agents/<slug>/skills/
If empty: the agent was provisioned without template content. Re-provision by deleting and recreating the agent (the branch will be re-seeded from template on provision).If the directory exists but skills aren’t running: check the agent’s OpenClaw config (openclaw.json) on its branch — the skills path must point at the right directory.
What you seeYou run:
docker compose exec gateway openclaw models auth login \
  --provider openai-codex --set-default
It prints a URL, you complete OAuth in your browser — then the CLI just sits there indefinitely.Why it happensOpenClaw’s OAuth flow tries a loopback HTTP callback on localhost:1455 first, then falls back to paste. If you’re completing OAuth on a different machine than the gateway (common with remote servers), the callback never fires — but the CLI waits for it forever.FixPre-occupy port 1455 to force the paste fallback:
# Terminal 1 — hold the port
docker compose exec gateway python3 -m http.server 1455
# Terminal 2 — run the login (it will prompt for paste)
docker compose exec gateway openclaw models auth login \
  --provider openai-codex --set-default
Complete OAuth in your browser, copy the redirect URL (http://localhost:1455/?code=...), paste it into terminal 2. You should see Auth profile saved. Kill the server in terminal 1.

Installer

Why it happensThe auto-install path (curl | sh get.docker.com) is Linux-only. Docker on Mac/Windows is a GUI app and can’t be installed from a script.Fix
  • macOS — download Docker Desktop for Mac, drag to Applications, launch it, wait for the whale icon, re-run the installer.
  • Windows — install WSL2, then Docker Desktop, then launch it, and re-run the installer from a WSL shell.
Why it happensBash pipes can buffer stderr or swallow /dev/tty reads in some terminals.FixClone the repo and run the script directly:
git clone https://github.com/yourhq/yourhq.git
cd yourhq
./installer/install.sh
Same prompts, guaranteed interactive.
Why it happensBuilding all four images in parallel peaks well past 4 GB RAM. A t3.medium with no swap has no room — the OOM killer reaps sshd or dockerd.FixPreferred: pull prebuilt images instead of building:
docker compose pull
docker compose up -d
If you must build, add swap first:
sudo fallocate -l 8G /swapfile && sudo chmod 600 /swapfile
sudo mkswap /swapfile && sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Then build one service at a time:
docker compose build ui
docker compose build gateway
docker compose build dispatcher
docker compose build runner

Database & data

What you seeSQL Editor stops with ERROR: relation "contacts" already exists or similar.Why it happensYou ran a migration against a project where some tables already exist (from a previous partial run or an older schema version).FixIf this is a throwaway project where losing data is fine:
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
GRANT ALL ON SCHEMA public TO postgres, anon, authenticated, service_role;
Then run every file in db/migrations/ in filename order again.
This destroys all data in the public schema. Back up first if you have anything worth keeping.
If it’s a live project, skip the failing statement and run the rest manually — but starting with a fresh Supabase project is usually faster.
What you seeYou’re logged in and the dashboard renders, but contacts/tasks/agents lists are empty even though rows exist in Supabase.Why it happensRow-level security is blocking reads. Either the authenticated role is missing USAGE on the schema, or table-level grants weren’t applied.FixIn Supabase SQL Editor:
GRANT USAGE ON SCHEMA public TO authenticated;
GRANT ALL ON ALL TABLES IN SCHEMA public TO authenticated;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO authenticated;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO authenticated;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated;
Refresh the UI. If data still doesn’t appear, check the browser console — you may see JWT issues (anon key mismatch, expired session). Log out and back in.

Performance

Why it happensPulling the prebuilt images from GHCR the first time takes a while — the gateway image alone is ~1.5 GB (Xtigervnc, XFCE, Chrome, OpenClaw, Node 24). Docker caches them after the first pull.FixJust wait. For progress visibility, pull explicitly before starting:
docker compose pull   # shows per-layer progress
docker compose up -d
Why it happensThe gateway runs Chrome + XFCE + OpenClaw simultaneously — ~1.5 GB RAM at idle. On a t3.small (2 GB) you’re likely swapping. Websockify also streams uncompressed framebuffer diffs, which is bandwidth-intensive over public internet.Fix
  • Upgrade to t3.medium (4 GB RAM) or larger
  • Access noVNC via Tailscale (direct peer-to-peer, much better throughput than going via public internet)
  • In the noVNC UI (top-left gear icon): set quality to 6 and compression to 9 — cuts bandwidth ~3x

Tired of debugging infrastructure?

If you’d rather focus on agents than Docker and networking, HQ hosted runs the same platform without any infrastructure to manage.

Getting more help

If nothing above matches, open an issue at github.com/yourhq/yourhq/issues with:
  • The exact error text (copy/paste, not a screenshot)
  • docker compose logs output for the failing service — last 200 lines
  • Host info: uname -a, cloud provider + instance type, or “Mac/Linux local”
  • Install method: curl | bash, direct clone, manual

Diagnostic bundle

To gather everything at once:
bash scripts/diagnostic-bundle.sh > diag.txt
This collects: docker compose ps, recent logs for each service, compose config with secrets redacted, .env keys (values redacted), docker --version, tailscale status, host OS info, and OpenClaw version. Attach diag.txt to your issue.
See also: Networking · Configuration · Agents · Database schema