troubleshooting
Troubleshooting.
Every Shoti error ends in a help link. Here is the fix for each, by area. Run shoti explain <topic> to read any of them offline.
auth
- Couldn't read your credentials — Shoti found ~/.shoti/auth.toml but couldn't read or parse it.
- OAuth provider required — A sign-in request reached the API without a provider.
- Redirect URL not allowed — The sign-in redirect URL's host isn't in the server's allowlist.
- Sign-in required —
shoti doctorfound no credentials at ~/.shoti/auth.toml. - Couldn't save your credentials — Sign-in succeeded, but writing ~/.shoti/auth.toml failed.
- Sign-out couldn't clear credentials — Sign-out couldn't remove ~/.shoti/auth.toml.
- Browser sign-in can't reach the app — Finishing sign-in in the browser didn't return you to the desktop app. The
shoti://link the browser hands back to isn't registered with your operating system. - Couldn't open a local sign-in port —
shoti logincouldn't bind a localhost port to receive the browser's sign-in callback. - Login state mismatch — The login callback's state parameter didn't match — a stale browser tab, or a possible CSRF attempt.
- Login timed out —
shoti loginwaited five minutes for the browser callback and gave up. - Sign-in code exchange failed — The browser sign-in finished, but exchanging the callback code for tokens failed.
- You're not signed in — A command needed Shoti credentials, but none were found at ~/.shoti/auth.toml.
- Session token expired — Your access token expired.
shoti doctor/shoti_statusmay still report "signed in" from local files, but authenticated calls now return 401 until the token is refreshed. The agent daemon normally rotates it automatically; if the daemon isn't running, the token stays stale. - Session expired — Your Shoti session expired and the agent daemon couldn't refresh it after more than seven days.
team
- Team name already taken — You already own a team with that name.
- Multiple teams, none active — You belong to more than one team, so
shoti initcan't pick one for you. - Team name required —
shoti initneeds a team name and none was given. - Role too low for that action — Your role on this team isn't high enough for what you tried to do.
- No valid invite emails — No valid email addresses remained after filtering the
shoti team invitearguments. - No active team selected — You're signed in, but no active team is set.
- Team selector matches more than one team —
shoti team usegot a prefix that matches more than one of your teams. - Can't remove the last owner — A team must keep at least one owner, and this would remove the last one.
- Not a valid team id —
shoti team use <id> --idgot an argument that isn't a team UUID. The --id flag (used by the desktop switcher) takes an exact team id and skips the network lookup, so it must be a real UUID. - Only owners can invite owners — You tried to send an owner-role invite, but only owners can do that.
- Invalid invite email — One or more of the invite addresses aren't valid emails.
- Invalid invite role — The invite role must be owner, admin, or member.
- Too many invites at once — That request had more invites than one call allows.
- User isn't on that team — The user you tried to act on isn't a member of that team.
- Team name too long — Team names are capped at 100 characters.
- Not a member of that team — You're not a member of the team you tried to act on.
- Team not found — The team id in the request doesn't match any team you can see.
- Couldn't finish joining — The desktop welcome step couldn't finish setting up your membership — usually a dropped connection mid-request.
broadcast
- Broadcast intent required —
shoti broadcastwas called with no intent. - Catch acknowledgement needs a numeric id — shoti_catch_ack was called without the integer catch id from the catch heads-up.
- Consolidation diff too large for one request — The world-map consolidation worker tried to submit a structural diff over the per-request size budget. The whole diff must fit one atomic request (the compare-and-swap on base_cursor can't span POSTs), so it can't be chunked like a seed batch.
- Broadcast not found — No broadcast with that event id exists on this team.
- Broadcast intent too long — Broadcast intent is capped at 4096 characters.
- Malformed idempotency key — The idempotency key must be 8-64 characters from [A-Za-z0-9_-].
- Broadcast needs an intent — A broadcast reached the API with no intent.
- Only the author can recall — Only the broadcast's original author can recall it.
- Invalid decision type —
shoti broadcast --typegot a value that isn't a known decision type. - Couldn't locate ~/.shoti — Shoti couldn't find or create the ~/.shoti directory.
- Couldn't queue your message — A broadcast or response couldn't be written to the local queue at ~/.shoti/queue.
- Recall needs an event id —
shoti recallneeds the event id of the broadcast to pull back. - Reply text required —
shoti respondgot an event id but no message. - Respond needs an event id —
shoti respondneeds the event id of the broadcast you're replying to. - Couldn't read the piped intent —
shoti broadcast -was told to read the intent from stdin, but the read failed.
agent
- Agent daemon stopped —
shoti doctorfound the agent daemon stopped. - Agent daemon not running — The background agent daemon isn't running, or its socket is unreachable.
- Agent pairing code rejected — The agent pairing code was rejected — it may have expired (15-minute TTL), already been used, or the owner denied the request.
- Agent lost its own binary — The agent couldn't resolve its own executable path — this happens when the binary moves mid-run.
- Couldn't start the agent daemon — Shoti couldn't spawn the background agent daemon.
- Couldn't report a fleet task result — shoti_report_result couldn't send your runtime's output back to the fleet task — the task may have expired, the session may have stopped, or the call hit a transient network error.
build
- Couldn't write the build brief —
shoti buildresolved the place, but couldn't write the temporary scoped brief file that Claude Code reads at startup. - Claude Code isn't on your PATH —
shoti buildhands the scoped place off to a local Claude Code session, but theclaudecommand wasn't found on your PATH. - That runtime can't accept a scoped brief directly — The chosen runtime has no way to receive a brief as an argument, so
shoti buildprinted the brief and the exact command to start it yourself instead of launching it. - No agent runtime found —
shoti buildlooked for claude, cursor, and codex on your PATH and found none. - Run
shoti buildinside your repo —shoti buildresolves a place to the code it owns, so it must run from inside the git repository the place is bound to — but the current directory is not a git repo. - --packet isn't valid JSON —
shoti build --intent --packetwas given a --packet value that failed to parse as JSON. - That place isn't on the work-map —
shoti buildwas given a place id that isn't in your team's work-map — it may be mistyped, from another team, or the map hasn't been seeded yet. - Place is bound to a different repo — The place you asked to build from is bound to a different repository than the one you're standing in, so its file scope wouldn't line up with your working tree.
- Multiple runtimes installed, none set as the default — More than one supported agent runtime is on your PATH and shoti has no remembered default, so it can't pick silently in a non-interactive shell.
- That runtime isn't installed — The chosen runtime (from --runtime, the remembered config.toml key, or the interactive pick) wasn't found on your PATH.
- Not a runtime shoti knows —
--runtimeor the rememberedruntimekey in config.toml named a value that isn't one of shoti's supported agent runtimes. - Name a session to dispatch to —
shoti fleet buildhands a place to one of your own live fleet sessions on another machine, so it needs a target session — but no--to <session-id>was given. - A runtime is installed but not wired — shoti doctor found an agent runtime (Cursor or Codex) on this machine whose shoti wiring is missing or stale — its sessions can't broadcast or hear the team until it's wired.
- No indexable source found — The cold-start seed indexed the chosen repo but found no source files in a language it parses (Go, TypeScript, TSX, or JavaScript), so there's nothing to turn into a map yet.
- Conflicting seed flags — shoti-seed was run with --rename and --name-new-only together. A rename pass targets exactly the already-persisted places that --name-new-only excludes, so the combination would spend naming quota and then skip the rename preview it was asked for.
- Choose a folder that's a git checkout — The cold-start seed turns a repo into your team's first map, so the chosen folder must be a git checkout — but it isn't one.
- That folder is a different repo — The map heard work in one repo, but the folder you picked derives to a different repo key. Adding it under the heard repo would bind the wrong code to the wrong places.
- The server rejected the seed — The cold-start seed reached api.shoti.ai, but the server rejected the places or bindings it tried to persist.
config
- Config value can't be empty —
shoti config set display-namewas given an empty value. - Invalid telemetry value —
shoti config set telemetrygot a value that isn't off, anonymous, or full. - Unknown config key —
shoti config setgot a key it doesn't recognize.
setup
- Aider is read-only in v1 — Aider sessions can read inbound broadcasts but can't send outbound ones in Shoti v1.0.
- Sync hooks into Conductor — Hooks were written, but Conductor mirrors agent configs through its own settings.
- Cursor rule skipped — not in a project directory —
shoti install-hookswired Cursor's mcp.json and hooks.json but skipped writing .cursor/rules/shoti.mdc because the working directory has no .git or .cursor directory. - --local requires --json —
shoti doctor --localwas run without--json. The--localflag only controls the machine-state JSON probe consumed by the desktop — it has no effect in the human-readable or--cidoctor path. - Unknown installer option — The installer was passed a flag it doesn't recognize.
- Install download failed — The installer couldn't download the shoti binary or its checksums from dl.shoti.ai.
- Couldn't locate the shoti binary —
shoti install-hookscouldn't resolve the path of its own binary to wire into the hooks. - Couldn't update a Claude Code config file — Shoti couldn't write its changes to a Claude Code config file under ~/.claude/.
- Unsafe binary path for hooks — Shoti refused to wire its hooks because the binary's path contains a shell metacharacter.
- curl is required to install — The installer needs curl (or GNU wget) to download over TLS; BusyBox wget can't enforce a secure transport.
- CLI distribution isn't live yet — The installer couldn't reach the Shoti CLI release channel — the download host may not be serving yet.
- Couldn't create a temp directory — The installer couldn't create a temporary working directory to download into.
- Install path has shell metacharacters — The chosen install directory contains characters (double-quote, backtick, $, %) that aren't safe to embed in the agent hook commands shoti writes.
- Unsupported platform — The installer doesn't ship a prebuilt binary for this operating system or CPU architecture.
- Couldn't verify the download — The installer couldn't verify the download's checksum or signature, or a required tool (minisign / sha256sum) was missing.
- No agent runtimes detected —
shoti install-hooksfound no agent runtimes to wire into. - Couldn't delete ~/.shoti —
shoti uninstallremoved the Claude Code wiring but couldn't delete the ~/.shoti/ directory. - Couldn't remove the hooks —
shoti uninstallcouldn't remove Shoti's hook entries from ~/.claude/settings.json. - Couldn't remove the MCP entry —
shoti uninstallcouldn't remove Shoti's MCP server entry from ~/.claude/settings.json. - Update failed its checksum — The binary
shoti upgradedownloaded did not match its published SHA-256 — a corrupted or tampered download. - Refusing to downgrade — The version
shoti upgraderesolved is the same as or older than the one you're running. - Couldn't fetch the update —
shoti upgradecould not download the release manifest or the new binary from dl.shoti.ai. - shoti is managed by a package manager —
shoti upgradedetected that this shoti was installed by a package manager (Homebrew, Scoop, Chocolatey, snap, apt), which owns the binary's files. - Can't replace the shoti binary —
shoti upgradecould not write over the installed binary — its directory isn't writable by you (e.g. a root-owned /usr/local/bin). - Update failed its signature —
shoti upgradecould not verify the minisign signature on the release — the update could not be authenticated. - Windows SmartScreen blocked the installer — Running the Shoti installer on Windows showed "Windows protected your PC." The beta installer isn't code-signed yet, so Microsoft Defender SmartScreen warns before anything new and unsigned runs.
- Update couldn't be installed — The desktop app downloaded an update, but installing it failed. The version you were running keeps running — nothing is lost.
demo
- Demo couldn't start —
shoti democouldn't set up its throwaway session directory. - Desktop demo can't find the app —
shoti demo --desktopcan't find the desktop app (thedesktop/folder) from the current directory. - That desktop/ folder isn't the Shoti app —
shoti demo --desktopfound adesktop/folder up the tree but itssrc-tauri/tauri.conf.jsonisn't Shoti's (the bundle identifier doesn't match), so it refused to runpnpm tauri devthere — running an unverified package's scripts could execute untrusted code. - Desktop demo needs pnpm —
shoti demo --desktopneeds pnpm and it isn't on your PATH. - Vignette unavailable with --desktop —
--vignetteisn't available with--desktop, which only runs the demo-hero story. - Demo couldn't set its environment —
shoti democouldn't set the environment variables that keep the demo offline and sandboxed. - Demo is offline by design — A network call was attempted from inside
shoti demo, which is offline by construction so it can never publish to a real team. - Invalid demo seed —
shoti demo --seedgot a value that isn't an integer.
network
- Can't reach the API — Shoti couldn't reach api.shoti.ai.
- Request timed out — The server took too long to respond during sign-in or setup.
- Network unreachable — Shoti couldn't reach api.shoti.ai over the network.
- Rate limited — The Shoti API is rate-limiting your requests.
- Couldn't reach the API to seed the map — The cold-start seed indexed your repo locally, but couldn't reach api.shoti.ai to persist the map.
billing
- Writes disabled for this team — Your team's entitlement state (trial ended, past due, or archived) blocks new writes.
- Seat limit reached — Adding this teammate would exceed your team's seat limit.
- Trial ended — Your team's trial has ended.
internal
- Wrong arguments — A
shoticommand got the wrong number of arguments. - Unregistered error code — An error surfaced with a code that isn't registered in Shoti's error catalog — an internal consistency check.
- Old
shoti initform —shoti initwas given a repository URL argument — the old v0.2 form. Shoti now hosts everything for you. - Migration needs the direct URL — A database migration step needs the direct (non-pooled) connection URL. This is an operator topic, not a user error.
- Migration failed — A database migration failed to apply. This is an operator topic, not a user error.
- Shoti isn't set up here —
shoti doctorfound no Shoti configuration. - Unknown ping source —
shoti ping --sourcegot a value that isn't a known agent. This is an internal test-ping the desktop uses to verify the liveness pipe.
Still stuck? hello@shoti.ai. Back to shoti.ai.