Sophon 2.0 is here
Sophon Docs
Troubleshooting

Common Issues

Quick fixes for the problems most Sophon users hit — connection failures, provider errors, sandbox issues, Node pairing, MCP handshake.

This is a triage checklist for the things that go wrong most often. For each symptom, the fix. If none of these apply, check Diagnostic Logs or reach out via Support.

Gateway won't start

Symptom: sophon exits immediately, or the Docker container restarts in a loop.

Check, in order:

  1. Port in use — default is 8080. lsof -i :8080 (or netstat -ano | findstr 8080 on Windows) shows what's holding it.
  2. Database unreachable — if using Postgres, verify connectivity: psql "<connection-string>" -c "SELECT 1".
  3. Invalid appsettings.json — JSON syntax error, bad config path. Look for the first error in startup logs.
  4. License expired (Enterprise) — license check runs early; expired license with no grace period blocks startup. Renew or reset tier to Pro temporarily.
  5. Vector DB unreachable (Pro/Enterprise) — Qdrant down blocks memory init. Check QDRANT_URL.

Fast test: docker logs sophon-gateway or ~/.sophon/logs/gateway-YYYYMMDD.log.

Can't log in / authentication loop

Symptom: Dashboard keeps redirecting to login; CLI says "Unauthorized."

Check:

  1. Time drift — JWTs are time-sensitive. ntpdate or equivalent to sync the clock.
  2. Cookie / CORS — if Dashboard URL differs from API URL, confirm Sophon:Cors:AllowedOrigins includes the Dashboard URL.
  3. Expired token — CLI tokens expire after 30 days by default. sophon login again.
  4. SSO misconfiguration (Enterprise) — check OIDC discovery URL is reachable and the authority matches the token's iss claim.

Test provider connection fails

Symptom: Adding an LLM provider (Anthropic, OpenAI, …) and clicking Test returns an error.

Check:

  1. API key is correct — paste into a quick curl test against the provider directly.
  2. Outbound network — Gateway needs egress to api.anthropic.com / api.openai.com / etc. Corporate firewalls may block these; add allowlist entries.
  3. Rate limit already exceeded — the first call might 429 if you've been testing from other tools. Wait a minute.
  4. Wrong region (Azure OpenAI, Google) — Azure OpenAI endpoints are region-specific; Gemini has separate generativelanguage.googleapis.com vs aiplatform.googleapis.com paths.

Logs will show the full HTTP response from the provider.

Chat hangs — agent status stuck on "thinking"

Symptom: A chat message sits with an AgentStatus: thinking event and never completes.

Check:

  1. LLM provider latency — check provider status pages. Anthropic / OpenAI occasionally have slow responses.
  2. Task queue backed up — Operations → System. If queue depth is high, either pause / drain or increase MaxConcurrentTasks.
  3. Tool call hanging — if the agent called a slow tool (web fetch, browser automation), tool execution can exceed its budget. Tasks → <task> shows current tool + duration. Cancel the task; next turn the agent will handle the "previous tool hung" gracefully.
  4. Budget exceeded — the pipeline short-circuits quietly. Check Settings → Models → Budget usage.

Skill execution errors

"Sandbox not available"

Docker isn't running or the sandbox image isn't pulled. Run:

docker ps                  # Is Docker up?
docker pull sophon/sandbox:latest

"Permission denied" in skill logs

The skill tried to write to a path outside its sandbox. Check the skill's manifest declares the required paths under sandbox.writablePaths.

"Network access denied"

Default sandbox has network disabled. Add "network": true and a "networkAllowlist" to the manifest.

Python import errors

Required packages aren't in the sandbox image. Either add them via pipDeps in the manifest or rebuild the sandbox image with the dependencies pre-installed.

Workflow not firing on cron

Symptom: Workflow is active, cron job exists, schedule time passes, nothing happens.

Check:

  1. Scheduler running — Operations → System → Scheduler status. Restart if degraded.
  2. Cron job enabled — sometimes paused inadvertently. sophon cron list shows status.
  3. Cron expression timezone — default is UTC unless otherwise specified. 0 9 * * * means 9am UTC, not local.
  4. Previous run still in flight — by default, concurrent executions are blocked. Check Workflows → Runs for a stuck run.
  5. Misfire — if the Gateway was down when the job should have fired, the misfire policy may have skipped it. Check Cron → History.

Approval requests not arriving on mobile

Symptom: Dashboard shows pending approvals; mobile doesn't get pushes.

Check:

  1. Device registered — mobile: More → Notifications. Should show "Registered" with a device name.
  2. approvalRequests category enabled — same screen.
  3. Quiet hours — during quiet hours no push is delivered to that device in any category, approval requests included. Nothing is queued for redelivery. The approval itself is unaffected: it keeps its own countdown and expires unapproved if nobody answers.
  4. Expo Push credentials — Admin → Settings → Push Notifications. Check delivery activity for errors.
  5. Notification permission on device — iOS: Settings → Sophon → Notifications. Android: same path.

Sophon Node

"Waiting for approval" forever

Ticket expired (15 minutes default), or the Dashboard didn't receive the pair request. Regenerate pairing credentials.

"Failed to connect to Gateway"

WebSocket or TLS issue:

  • Gateway URL reachable from the Node machine? curl <gateway>/health
  • Self-signed cert? Install in OS trust store.
  • Firewall blocking WebSockets? Fall back to HTTP polling transport.

Commands time out

  • Node online but scopes missing. Check Settings → Devices → <node> → Permissions.
  • macOS Accessibility not granted — grant for sophon-node in System Settings.
  • Linux Wayland — ydotool daemon not running, or compositor blocks automation.

MCP handshake errors

"Invalid token" from external MCP server

The token in env.GITHUB_PERSONAL_ACCESS_TOKEN (or similar) isn't what the server expects. Test the token manually against the service's API before blaming MCP.

"Tool not found" when agent tries to use a bridged tool

External server connected at start but dropped. Settings → MCP → Connections → <server> → Activity for last heartbeat. Restart the server.

Claude Desktop doesn't see Sophon tools

claude_desktop_config.json may have a typo, or the stdio subprocess fails to start. Run sophon mcp serve --stdio manually in a terminal — if it errors there, fix the error first.

401 on SSE / HTTP MCP

Token revoked or token label mismatch. Regenerate in Settings → MCP → Server → Tokens.

Documents

Upload stuck on "extracting"

Large PDF with OCR. Look in logs for OCR errors — usually a Tesseract dependency issue. For PDFs with extractable text (not scans), extraction is fast; for scans it can take minutes per page.

Q&A returns no results

  1. Wait for status: ready on the document. Uploads take seconds to minutes to process.
  2. Vector index empty? On Personal tier, only keyword search works — semantic queries may miss.
  3. Reindex: sophon documents reindex <id>.

Voice

Start from the banner on the Voice page — it is designed to tell "not set up" apart from "broken." Full reference in Sophon Voice.

The Voice page says speech "isn't configured"

Not an error. An info-tone banner means there's no active provider on that side, which is the expected state on a fresh install. Voice keeps working through the browser's own speech recognition and voice — nothing degrades to text-only, and there's no "type instead" path.

The browser recognizer needs a browser that has one: Chrome, Edge or another Chromium browser, or Safari. Firefox has none, so hands-free isn't offered there; push-to-talk still shows and fails when you press it. To move to server-side transcription, an admin adds a speech-to-text provider in Settings → Voice → Listening — Deepgram, OpenAI, Azure Speech, Google Cloud Speech, ElevenLabs or Sophon Managed Speech (Voice Providers).

The banner says a provider "is failing"

A warning-tone banner means at least one registered provider on that side failed its health checks and none on that side is active. The banner names it. Things to know before you chase it:

  1. The status lags a real outage. Providers are swept every 15 minutes and marked failing only after two consecutive failures, so it can take around half an hour to show.
  2. It resets on a Gateway restart — health status is held in memory, not persisted.
  3. A failing provider sitting next to a healthy active one shows no banner at all. The banner only appears when nothing on that side is active. Use sophon voice status for the per-provider view.

Hands-free stopped listening on its own

Two independent timers close the mic, and both are per-user settings in Voice Center:

  • Silence timeout (default 30 s) — that long with literal silence ends listening. With browser recognition this rarely bites: the recognizer ends itself within seconds of a pause and hands-free just re-arms.
  • Inactivity limit (default 120 s) — no real exchange for about two minutes turns hands-free off. This is usually what stopped it.

On the Command Bridge the bar disarms itself and keeps the reason on screen. Press the mic again to start over.

A prompt stopped re-asking and is just sitting there

By design. Two unclear answers each got a re-prompt; a third closes the mic rather than guessing or looping forever. The card stays and its own countdown keeps running — tap Approve / Reject, or press the mic again to answer out loud. Mobile caps re-prompts the same way, and a recognizer that ends in silence counts as an attempt.

If a High- or Critical-risk approval keeps coming back as unclear, check you're saying the full phrase: those need "yes, approve", not a bare "yes". See Approvals & Questions.

A reply carries a red "not spoken" notice

The notice appears when provider speech was expected and can't happen, and its text names the actual cause — a registered provider failing health checks, providers registered but all inactive, speech output set to Configured provider only with nothing available, or native speech fallback turned off with no provider. The six exact messages and what each one means are in Spoken Replies.

A fresh install with no provider and native fallback on shows no notice: the browser voice reads the reply, which is the intended zero-configuration path.

The reply shows in chat but nothing is spoken at all

Real causes of silence, in the order worth checking:

  1. Native speech fallback is off in Voice Center.
  2. Speech output is Configured provider only — that silences the browser entirely, including the fallback reply the server still sends.
  3. Speech output is OS / browser only while native fallback is off.
  4. The browser has no speechSynthesis.
  5. The voice session itself ended — a voice error was raised. Check that before assuming the reply was simply never spoken.

Robotic / choppy speech

Speech is synthesized sentence by sentence so it can start before the reply is finished. A sentence longer than 280 characters is split at clause boundaries first, so an unpunctuated wall of text no longer grows a buffer indefinitely — but it will be split at commas, which can sound abrupt. Nudging the agent toward ordinary punctuation (via SOUL.md) still reads better.

Code blocks and tables are meant to be replaced with "shown on screen," and short ones are. Longer ones, and code containing semicolons or periods, can still be read aloud with the formatting stripped — see Spoken Replies.

No audio on mobile

Device audio permission first. Then check speech output and the TTS provider under More → Voice Center: with no provider and native fallback on, the phone's own voice speaks the reply.

A node's device page has no Voice tab

The tab needs both: you must be an Admin (the runtime routes behind it are Admin-only), and the node must report at least one voice.* command capability to the Gateway. A node running an older build, or one that hasn't reconnected since it was upgraded, reports nothing and gets no tab. Separately, the Gateway's node-facing voice routes stay off until an operator sets Sophon:Voice:NodeWake:Enabled — see Voice Surfaces.

CLI opened the classic prompt instead of the full-screen chat

Symptom: sophon chat shows the pinned-input shell, or the classic framed prompt, rather than the full-screen chat.

The full-screen chat is the default as of 2.0. It falls back, in this order:

  1. Explicitly disabled — SOPHON_CLI_FULLSCREEN=0 in the environment, or "fullScreen": false in ~/.sophon/config/cli.json. Environment always beats the config file.
  2. Accessibility mode — SOPHON_CLI_ACCESSIBLE=1, or an active screen reader on Windows. The classic linear surface is the accessible one, deliberately.
  3. Redirected input or output — piping stdin/stdout (or TERM=dumb) drops out of full-screen by design.
  4. Terminal too small — below 70×18 (columns × rows) the pinned shell is genuinely better. Resize and start a new session.
  5. The Dashboard's embedded terminal — it always uses the classic surface.

Two layers below that have their own escape hatches: SOPHON_CLI_PINNED=0 / "pinnedInput": false goes back to the classic prompt, and SOPHON_CLI_V2=0 / "v2": false goes back to the legacy CLI.

If a crashed session leaves your terminal in a broken state — a stuck scroll region, no echo, output confined to part of the screen — reset it:

sophon doctor --reset-terminal

See Interactive Chat for the full terminal requirements.

Where to go next