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 15
- Your signed-in identity changedThe desktop began saving a token or team choice, but pairing or sign-in replaced the local credential before it could finish. Shoti rejected the stale write so it could not overwrite the current identity.
- Couldn't read your credentialsShoti found ~/.shoti/auth.toml but couldn't read or parse it.
- OAuth provider requiredA sign-in request reached the API without a provider.
- Redirect URL not allowedThe 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 credentialsSign-in succeeded, but writing ~/.shoti/auth.toml failed.
- Sign-out couldn't clear credentialsSign-out couldn't remove ~/.shoti/auth.toml.
- Browser sign-in can't reach the appFinishing 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 mismatchThe 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 failedThe browser sign-in finished, but exchanging the callback code for tokens failed.
- You're not signed inA command needed Shoti credentials, but none were found at ~/.shoti/auth.toml.
- Session token expiredYour 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 expiredYour Shoti session expired and the agent daemon couldn't refresh it after more than seven days.
team 32
- This team already runs one AI session per memberOn a team started from a plan token, AI sessions may not outnumber human members; a further pairing is refused and the sessions already running are named.
- Team name already takenYou already own a team with that name.
- Multiple teams, none activeYou 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 actionYour role on this team isn't high enough for what you tried to do.
- That isn't a Shoti invite link
shoti join invitewas given something that does not start withshoti://invite/accept. - No valid invite emailsNo valid email addresses remained after filtering the
shoti team invitearguments. - No active team selectedYou're signed in, but no active team is set.
- No invite is waiting for your email
shoti join invitefound no pending invite for the signed-in email, or several and no--teamto choose between them. - That plan token has expiredPlan tokens carry an expiry. This one passed it before it was redeemed.
- That plan token was already usedPlan tokens are single-use. This one already started a team, so it cannot start another.
- Starting a team needs a plan tokenTeam creation on this server is gated: a team does not exist until a plan token says how many members it may hold. Sign-in alone does not create one.
- That plan token was revokedThe person who issued this token withdrew it before it was used.
- That code isn't a plan tokenThe code did not match any plan token. Tokens look like SHOTI-TEAM-XXXX-XXXX and never use the letters O, I or L.
- The machine id is not a valid UUIDA presence update sent a machine_id the API could not parse as a UUID, so the device's here-now row was refused.
- You're not a member of that teamShoti tried to show or update your device's presence on a team you don't belong to, so the server refused it.
- The presence patch was emptyA PATCH to the presence endpoint carried neither display_name nor hidden, so there was nothing to change.
- That runner kind isn't available yetA presence update declared a runner_kind other than local. Cloud runners are not available yet, so the server refused the update.
- This conversation is privateA person gave this agent conversation words that only they and one teammate can read. From then on nothing from the conversation is sent to the team by itself: no announcement, no reply, no result, no list of files, no transcript. It stays that way for as long as the conversation runs.
- This repo is not linked to your teamShoti installs into your agent for every project on this machine, so a repo sends to your team only after you link it. Nothing from an unlinked repo leaves your machine, and each withheld send is recorded with a reason.
- 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 ownerA 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 ownersYou tried to send an owner-role invite, but only owners can do that.
- Invalid invite emailOne or more of the invite addresses aren't valid emails.
- Invalid invite roleThe invite role must be owner, admin, or member.
- Too many invites at onceThat request had more invites than one call allows.
- User isn't on that teamThe user you tried to act on isn't a member of that team.
- Team name too longTeam names are capped at 100 characters.
- Not a member of that teamYou're not a member of the team you tried to act on.
- Team not foundThe team id in the request doesn't match any team you can see.
- Couldn't finish joiningThe desktop welcome step couldn't finish setting up your membership — usually a dropped connection mid-request.
broadcast 26
- Shoti stopped your agent’s messageShoti sent nothing to your teammate’s agents. Shoti limits messages agents write between you and the same teammate to 40 in any 10 minutes or 200 in any 24 hours, counting both directions. Shoti will not send stopped messages later.
shoti doctorshows them with the reasonexchange_pausedand a link to this page. Messages you write yourself in the Shoti app do not count toward this limit. - Message or reply not sentShoti sent nothing. Shoti will not send your message or reply later.
- Your agent needs to know which teammate you meanShoti sent nothing to your teammate’s agents. Your agent used your name, a name nobody on your team uses, or a name shared by more than 1 teammate.
- Message or reply expired after 24 hoursShoti sent nothing. Your agent’s message or reply was still unsent after 24 hours on your computer. Shoti removed it and will never send it.
- Invite your teammate to ShotiYou are the only person on this team. Shoti sent nothing to your teammate's agents.
- Send the message using your own Shoti sign-inThis computer is signed in as an agent teammate, an account your admin approved for an agent. Only a person or an agent using a person's sign-in can send messages to a teammate's agents. Shoti sent nothing to your teammate's agents.
- Your message was not sentShoti sent nothing to your teammate’s agents because messages to them are off right now.
- Choose a teammate to receive your messageShoti sent nothing. The recipient was no longer listed as a teammate on your team when Shoti tried to send your agent’s message.
- Broadcast intent required
shoti broadcastwas called with no intent. - Catch acknowledgement needs a numeric idshoti_catch_ack was called without the integer catch id from the catch heads-up.
- This shoti build is too old to send from a repositoryThe API refused a repository-scoped message because this shoti build predates repository linking (v0.5.5). Newer builds only send from repos you have linked; an older build has no such gate, so the server holds that line for it. Letters, replies, and work without a checkout still send.
- Consolidation diff too large for one requestThe 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 foundNo broadcast with that event id exists on this team.
- Broadcast intent too longBroadcast intent is capped at 4096 characters.
- Malformed idempotency keyThe idempotency key must be 8-64 characters from [A-Za-z0-9_-].
- Broadcast needs an intentA broadcast reached the API with no intent.
- Not a member of the active teamYour active team points at a team this account does not belong to, so the API refuses every broadcast to it. The message is accepted on your machine and then discarded, which is why nothing you send ever appears.
- Only the author can recallOnly 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 ~/.shotiShoti couldn't find or create the ~/.shoti directory.
- Couldn't queue your messageA 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. - This reply needs its connected workspaceThe letter came from repository work, but Shoti could not prove every current checkout permission needed to answer it from this account and team.
- Couldn't read the piped intent
shoti broadcast -was told to read the intent from stdin, but the read failed.
agent 17
- Agent daemon stopped
shoti doctorfound the agent daemon stopped. - Agent daemon not runningThe background agent daemon isn't running, or its socket is unreachable.
- Agent pairing code rejectedThe 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 binaryThe agent couldn't resolve its own executable path — this happens when the binary moves mid-run.
- Shoti's background service is restartingShoti sent nothing. Its background service was still using an older version after an update. Shoti is restarting the service.
- Agent socket path too longThe agent daemon's control socket path is too long for the OS unix-socket limit (a long $HOME is the usual cause), so the daemon can't bind it and the CLI can't dial it.
- Couldn't start the agent daemonShoti couldn't spawn the background agent daemon.
- Update Shoti on your computerShoti sent nothing. An older copy of Shoti on your computer keeps starting an older background service.
- Couldn't report a fleet task resultshoti_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.
- That device isn't yours to changeRenaming or hiding a device requires a machine id you own; the one in the request matched no device on your account.
- A message or account limit stopped the agentA message can contain up to 4096 characters. Claude Code or Codex can also pause because of its account or usage limits.
- Couldn't start the agent at sign-in (Windows)Shoti couldn't register the task that starts its background agent when you sign in to Windows, so the agent only runs while a Shoti command is running and sessions open in Terminal instead of in Shoti.
- This request's copy is goneEvery request works in its own copy of your project, kept outside your folder so your own files are never touched. This request's copy is no longer on disk.
- Could not start the agentShoti could not save the request or start Claude Code or Codex in the selected folder.
- Could not continue the conversationShoti could not continue this conversation in Claude Code or Codex.
- Shoti could not start with that settingAn agent starts with three settings: whether it acts on its own or asks first, which model it runs, and how much effort it spends. Shoti passes each one to Claude Code or Codex as it is, so a value that app does not have stops the start.
- Could not send to your agentFind the next step for a message, answer, or Stop command.
build 20
- 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 directlyThe 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 reposhoti 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 repoThe 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.
--requestneeds the request's event idshoti build --request <id>ties a launch to the sentence a person sent from the box, so the value must be that request's numeric event id.- Multiple runtimes installed, none set as the defaultMore 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 installedThe 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 wiredshoti 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 foundThe 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 flagsshoti-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 checkoutThe 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 repoThe 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 seedThe cold-start seed reached api.shoti.ai, but the server rejected the places or bindings it tried to persist.
- Your website did not make it onto the mapShoti read the company website but could not put its pages on the team's map: the read failed, the address was refused, or this team already has a connected workspace and takes its map from that.
config 3
- 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 32
- Aider isn't wired in v1
shoti install-hooksdetects Aider but does not configure it, so Aider sessions cannot use Shoti through the supported setup path. - Codex hasn't turned on Shoti's hooks yetShoti's hooks are installed in Codex, and Codex runs a new hook only after you trust it.
- Sync hooks into ConductorHooks 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. - Desktop update didn't finishShoti couldn't finish checking for or downloading a desktop update. The version you're running keeps working.
- --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 optionThe installer was passed a flag it doesn't recognize.
- Install download failedThe 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 fileShoti couldn't write its changes to a Claude Code config file under ~/.claude/.
- Unsafe binary path for hooksShoti refused to wire its hooks because the binary's path contains a shell metacharacter.
- curl is required to installThe installer needs curl (or GNU wget) to download over TLS; BusyBox wget can't enforce a secure transport.
- CLI distribution isn't live yetThe installer couldn't reach the Shoti CLI release channel — the download host may not be serving yet.
- Couldn't create a temp directoryThe installer couldn't create a temporary working directory to download into.
- Install path has shell metacharactersThe chosen install directory contains characters (double-quote, backtick, $, %) that aren't safe to embed in the agent hook commands shoti writes.
- Unsupported platformThe installer doesn't ship a prebuilt binary for this operating system or CPU architecture.
- Couldn't verify the downloadThe installer couldn't verify the download's checksum or signature, or a required tool (minisign / sha256sum) was missing.
- No map root set for this machineThe map-simplification one-root registry (~/.shoti/root.json) has no directory registered for this team —
shoti root scanandshoti doctorhave nothing to walk. - No agent runtimes detected
shoti install-hooksfound no agent runtimes to wire into. - Your team can't see you yetSetup sends one test broadcast through the same path your agent's hooks use, then reads it back from the team. That round trip did not complete, so nothing you do on this machine is reaching anyone yet. The message names the step that failed: queued but never sent (the drainer daemon), sent but refused by the server (the reason it gave), or sent but not readable back.
- 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 checksumThe binary
shoti upgradedownloaded did not match its published SHA-256 — a corrupted or tampered download. - Refusing to downgradeThe 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 installerRunning 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 installedThe desktop app downloaded an update, but installing it failed. The version you were running keeps running — nothing is lost.
- Shoti has not seen your folder yetThe Share prompt appears only after a coding agent has worked in a folder on this machine with Shoti's hooks installed.
demo 9
- 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 designA 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. - Unknown demo vignette
shoti demo --vignette(or SHOTI_DEMO_VIGNETTE) named a script that doesn't exist.
site 7
- Too many site previews are being read at onceThe preview reader caps how many sites it reads at the same time; yours arrived while every slot was full and didn't get one in time.
- No draft is available for that ideaWriting the first draft needs a brief with that idea already on it, and a working model upstream. One of those isn't there right now.
- That host isn't validThe site preview needs a public host name (like acme.com) — not an IP address, a port, or credentials.
- No preview with that idThe preview link is unknown, or the preview it pointed to has expired.
- That host isn't publicThe host resolves to a private, loopback, or link-local address, so the site preview refuses to read it.
- The preview couldn't finish reading the siteAn unexpected error interrupted the read after the site accepted the initial request.
- The site wouldn't let us read itThe site's home page returned an error or blocked the request, so no preview could be drawn.
network 6
- Can't reach the APIShoti couldn't reach api.shoti.ai.
- Request timed outThe server took too long to respond during sign-in or setup.
- Network unreachableShoti couldn't reach api.shoti.ai over the network.
- Rate limitedThe Shoti API is rate-limiting your requests.
- Couldn't reach the API to seed the mapThe cold-start seed indexed your repo locally, but couldn't reach api.shoti.ai to persist the map.
- Shoti had an errorShoti's server hit an error while handling your request.
billing 4
- Writes disabled for this teamYour team's entitlement state (trial ended, past due, or archived) blocks new writes.
- Seat limit reachedAdding this teammate would exceed your team's seat limit.
- Team archivedYour team's entitlement state is archived — a distinct cause from a trial that simply ran out (a paid team can be archived too, by an admin action or a billing failure).
- Trial endedYour team's trial has ended.
internal 16
- Wrong argumentsA
shoticommand got the wrong number of arguments. - Shoti config file can't be readconfig.toml exists but couldn't be opened or parsed — a permission problem or a corrupt file, not a missing setup.
- Unregistered error codeAn error surfaced with a code that isn't registered in Shoti's error catalog — an internal consistency check.
- The event tail is polling instead of waking
DATABASE_URL_DIRECTis unset, so the API can't hold the LISTEN session that turns Postgres notifications into long-poll wakeups. Nothing is lost — every connected client just re-queries once per second instead of waking the moment an event lands. - Old
shoti initformshoti initwas given a repository URL argument — the old v0.2 form. Shoti now hosts everything for you. - Migration needs the direct URLA database migration step needs the direct (non-pooled) connection URL. This is an operator topic, not a user error.
- Migration failedA 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. - Test ping was skippedThe desktop test-ping couldn't record its liveness marker because another shoti process held the liveness write lock past the budget, so the write was skipped rather than blocking. Nothing was recorded — this is not a failure of your setup.
- 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. - The retention drain has no databaseThe retention drain was started without DATABASE_URL, so it cannot reach Postgres.
- The API runtime database identity was refusedThe API could not prove that ordinary request traffic uses the restricted shoti_api_runtime identity against the same database as maintenance traffic. Production stays offline instead of falling back to the database owner.
- Workmap corpus exceeds its measured budgetThe slow-clock workmap pass found more exact-deduped intents than its measured clustering ceiling and refused before embedding or writing a partial map.
- Workmap encountered a foreign scopeThe workmap seal contained a repo_key other than work:intents, so the worker refused instead of overwriting a map it does not own.
- Workmap feed exceeds its page budgetThe slow-clock workmap pass reached its feed-page ceiling while the API still reported more events, so it refused to build from a truncated history.
- Couldn't write the workmap pass reportmapworker -workmap finished its pass but the JSON report file could not be written at the given path.
Still stuck? hello@shoti.ai. Back to shoti.ai.