Skip to content
yottacode v0.5.0 is out! ๐ŸŽ‰ See the release notes โ†—
Troubleshooting

Troubleshooting

Missing model or base URL

If yottacode exits with a configuration error, set both values:

export YOTTACODE_MODEL=<your-model-id>
export YOTTACODE_BASE_URL=https://api.openai.com/v1

For remote providers, also set an API key:

export YOTTACODE_API_KEY=sk-...

Or run:

yottacode setup

Connection refused or provider errors

Check that the provider is running and the base URL is correct:

curl "$YOTTACODE_BASE_URL/models"
yottacode doctor

For Ollama:

ollama serve
ollama pull qwen3.5:latest

Use http://localhost:11434/v1 as the base URL.

Model not visible

Run:

yottacode doctor
yottacode model fetch

Common causes:

  • wrong provider account or API key
  • model id typo
  • provider does not expose the model on /models
  • using a cloud model name against a local/custom endpoint

Tool call loop hits max iterations

Default max iterations is 100. Raise it for unusually large tasks:

yottacode --max-iterations 300

Keep the limit finite; it protects you from runaway tool loops.

cannot unmarshal string into Go struct field โ€ฆ of type int

Seen as a repeating tool error (e.g. web_search: invalid args: json: cannot unmarshal string into Go struct field .max_results of type int) with the model retrying the same call. Some open models โ€” notably Meta Llama 3.1/3.3 instruct on NVIDIA NIM, Ollama, and vLLM โ€” emit numeric/boolean tool arguments as JSON strings ("5" instead of 5).

yottacode now normalizes these against each tool’s schema automatically, so upgrading resolves it with no configuration. If you still see it, the model is likely emitting the tool call as plain text rather than a structured call โ€” a separate model limitation that argument normalization cannot fix; switch to a model that supports structured tool calling (e.g. NVIDIA’s Nemotron, Mistral, Qwen, or DeepSeek on the same endpoint).

web_search fails or returns no results

web_search has two backends. OpenAI, xAI, and explicitly enabled Anthropic profiles use provider-native search. Ollama, NVIDIA NIM, and generic OpenAI-compatible profiles use the local DuckDuckGo HTML fallback.

The fallback requires direct outbound HTTPS access to html.duckduckgo.com. OpenAI-auth uses hosted Codex web search first and keeps this fallback available if the hosted request is rejected. HTTP 403/429 responses usually mean bot protection or rate limiting; CAPTCHA/consent messages mean DuckDuckGo returned a challenge page; and a no-results parser error means the upstream HTML contract changed. These are backend failures, not proof that the query has no results. Retry later, verify proxy/DNS/egress access, or use fetch_url when you already know the target page. For reliable production search, configure a provider-native search-capable profile rather than depending on scraped HTML.

adapter: empty completion on NVIDIA NIM

Some NVIDIA NIM models have returned an empty streaming response when optional streaming usage reporting is requested. yottacode omits that optional usage probe for NVIDIA NIM and other local/free OpenAI-compatible endpoints, so upgrading resolves it. If the error persists, run yottacode doctor to verify the model id and endpoint, then try a fresh session to rule out a stale provider-side stream or over-large context.

unexpected end of JSON input, or a provider 400 that repeats every turn

Two linked symptoms from one cause โ€” a tool call that arrived with empty or truncated JSON arguments:

  • write_file: invalid args: unexpected end of JSON input (a tool ran against an empty argument string), or
  • a strict provider (notably NVIDIA NIM) returning 400 Bad Request with Expecting ',' delimiter โ€ฆ on every turn โ€” including unrelated prompts, and even after switching models โ€” because the malformed call was replayed from conversation history into each request body.

yottacode now normalizes an empty arguments payload to {}, rejects a genuinely truncated call before it runs or enters history, and re-sanitizes replayed history when building each request, so a bad call can no longer wedge the session. Upgrading resolves it. If a session started on an older build is still stuck, begin a new session to drop the already-poisoned history.

Sandboxed tests cannot resolve DNS or execute Go test binaries

If sandboxed run_tests fails with lookup proxy.golang.org on [::1]:53 (or a similar loopback DNS refusal), upgrade yottacode so new sandbox sessions get the default runtime DNS resolvers. If your network requires internal resolvers, override them in config instead of baking /etc/resolv.conf into an image:

[sandbox]
backend = "podman"
dns = ["10.0.0.53"] # example VPN/corporate resolver IP

If sandboxed Go tests fail with fork/exec /tmp/go-build.../*.test: permission denied, upgrade yottacode. Sandboxed run_tests now keeps /tmp mounted noexec for hardening but exports TMPDIR, GOTMPDIR, HOME, XDG_CACHE_HOME, and XDG_CONFIG_HOME under /var/tmp/yottacode-go/<workspace>/ inside the sandbox so Go can compile and execute test binaries safely, and disables Go telemetry with GOTELEMETRY=off, so tests should not leave repo-root .cache/, .config/, .local/, .yottacode/tmp/, .scratch/, or go/ directories that would break later go test ./... discovery or workspace-root tests.

If an older run already created those directories, remove them before opening a PR. Git status/readiness tools summarize those generated roots instead of printing every file, but the tree should still be cleaned before review.

Sandboxed run_tests feels slow, especially on the first Go command of a session

GOCACHE and GOMODCACHE point at a shared, host-mounted /var/tmp/yottacode-<uid>/sandbox-go-cache/ directory that persists across sessions (a fresh sandbox container is created per session โ€” see docs/sandbox.md). If you’re on an older yottacode build, that cache instead lived inside the container’s own ephemeral filesystem and was destroyed with the container at session end, so every new session paid a full go mod download plus full recompile on its first Go command. Upgrading resolves it; if tests still feel slow on every session’s first run after upgrading, confirm /var/tmp/yottacode-<uid>/sandbox-go-cache/ exists and is growing between runs (du -sh /var/tmp/yottacode-$(id -u)/sandbox-go-cache) โ€” an empty or unchanging directory usually means the running yottacode binary/session predates this fix; rebuild/restart and retest. sandbox.cpus (default 4) also caps how parallel a cold build/test run can be; raising it further in config.toml trades host resources for faster sandboxed builds.

Tests or background agents fail with PID/resource errors

Run yottacode doctor and inspect the Sandbox section. On Linux it reports the current cgroup’s pids.current, pids.max, remaining PID slots, zombie count, and free bytes/inodes for local scratch and cache paths without starting Podman. Errors such as resource temporarily unavailable, cannot fork, or fork/exec usually mean PID capacity is exhausted; no space left on device may mean either bytes or inodes are exhausted. run_tests reports these as a typed environment_failure with bounded command output and does not retry.

Background Agent/dispatch admission keeps a small absolute PID reserve so the TUI and recovery commands can still run. Stop completed or stuck subagents first. If zombies or leaked children remain, exit and restart yottacode (and, if the cgroup is owned by a container/service, restart that owner) so its init process can reap children. A generic foreground run_bash is intentionally still available for diagnosis and cleanup.

When no sandboxed jobs or yottacode sessions are running, caches may be removed safely; they are rebuilt on demand:

rm -rf /var/tmp/yottacode-$(id -u)/sandbox-go-cache
rm -rf ~/.yottacode/host-go ~/.yottacode/host-shell

Do not remove those directories while commands are using them. Repo-local .yottacode/host-go or .yottacode/host-shell directories indicate an older or inherited workspace-local HOME; remove them after stopping jobs and before opening a PR.

The trust prompt fires on every launch

The first-launch trust prompt records cwd in ~/.yottacode/trusted-roots.json on Yes. If you see it again on a directory you already accepted, the cwd is most likely a fresh path (different absolute path, different worktree, different bind-mount). List and add directly:

yottacode trust list
yottacode trust add /path/to/repo

Trust covers every subfolder of an added root. To bypass the prompt in CI runs, set YOTTACODE_TRUST_ALL=1 (session-only โ€” does not persist).

Approval prompts are too frequent

Use project-local allow rules for operations you trust:

{
  "permissions": {
    "allow": ["Bash(go test *)", "Edit(docs/**)"]
  }
}

Save personal rules in .yottacode/permissions.local.json and gitignore that file.

A saved memory is wrong or stale

Inspect and prune agent-managed memories:

yottacode memory list --scope user
yottacode memory list --scope project
yottacode memory forget --scope <user|project> <name>

Or browse them in the TUI: /memory โ†’ Browse user memories / Browse project memories, then d on the offending entry. Restart yottacode or reload memory from the TUI so the active session picks up the change.

The agent keeps making the same mistake

Put durable corrections in curated memory:

  • user-wide preference: ~/.yottacode/USER.md
  • repo-specific convention: ./.yottacode/YOTTACODE.md

Open the memory picker:

/memory

Large session or context warnings

Use:

/summarize

or start fresh with:

/clear

Summarization snapshots are saved before history is compressed.

Pasted text is collapsed in the input

Large pastes are shown as a short marker to keep the input line usable. The full pasted text is still sent when you submit.

Terminal rendering looks odd after resize

The TUI runs full-screen (alt-screen) and re-renders the whole frame โ€” including its own scrollable conversation transcript โ€” on every resize, so this shouldn’t come up in normal use. If your terminal emulator itself mishandles the resize (rare), restarting yottacode always recovers cleanly; the saved session can be resumed.

Stale edit or patch target

If an edit_file old string or apply_diff hunk no longer matches the file, the tool result is recoverable retry guidance, not a session failure. The TUI shows it as a compact stale-target hint; the agent should re-read the current file text and retry with fresh context.

ChatGPT OAuth from WSL without a Linux browser

A browser does not need to be installed inside WSL. Run yottacode in WSL and complete OpenAI’s browser-based OAuth flow in a Windows browser. An existing ChatGPT account and a browser somewhere are still required; openai-auth does not provide terminal-only account signup.

  1. Verify yottacode is installed in WSL:

    yottacode --version
  2. Check that the fixed callback port is free. No output is expected:

    ss -ltnp | grep ':1455' || true
  3. Start the login and leave it running:

    yottacode openai-auth login

    yottacode prints an https://auth.openai.com/... authorization URL. If automatic browser launch fails, copy the complete URL into Edge, Chrome, Firefox, or another Windows browser, then sign in and approve access.

  4. After approval, the Windows browser redirects to http://localhost:1455/auth/callback?.... Windows-to-WSL localhost forwarding normally delivers this request automatically. Return to WSL and wait for model discovery to finish.

  5. If the browser reports that it cannot connect, leave the original login running, copy the entire callback URL from the Windows browser address bar, and run this in a second WSL terminal:

    read -rsp "Paste the complete callback URL: " CALLBACK_URL
    echo
    curl --fail --silent --show-error "$CALLBACK_URL"
    unset CALLBACK_URL

    The original login should continue immediately. Using read -s keeps the short-lived authorization code off the screen and out of shell history. Do not share the callback URL.

  6. Verify the saved login:

    yottacode openai-auth status
    # Machine-readable alternative:
    yottacode openai-auth status --json
  7. Configure the provider with one of the model IDs accepted by the login scan:

    export YOTTACODE_PROVIDER=openai-auth
    export YOTTACODE_BASE_URL=https://chatgpt.com/backend-api/codex
    export YOTTACODE_MODEL=<accepted-model-id>
    yottacode

    Use /model list inside yottacode to inspect the models available to the account.

To persist the settings for Bash, replace the model placeholder and add them to ~/.bashrc:

cat >> ~/.bashrc <<'EOF'

# yottacode using a ChatGPT subscription
export YOTTACODE_PROVIDER=openai-auth
export YOTTACODE_BASE_URL=https://chatgpt.com/backend-api/codex
export YOTTACODE_MODEL=<accepted-model-id>
EOF
source ~/.bashrc

If login waits indefinitely, make sure the original command is still running. Callback URLs cannot be reused after that process exits because the OAuth state and PKCE verifier belong to that login attempt. Credentials and discovered models are stored under ~/.yottacode/auth/; do not print, copy, or share openai-auth.json.

ChatGPT OAuth: callback port already in use

openai-auth uses a fixed loopback callback port required by the OAuth redirect allow-list. If sign-in says the callback port is already in use, another sign-in is still holding it โ€” often an abandoned browser flow in this or another yottacode instance.

Retrying inline now closes any pending sign-in in the current TUI before starting a new one. If the holder is a different process or user, free that process and retry; on Unix-like systems, sudo lsof -i :1455 shows the owner when permissions allow it.

ChatGPT OAuth: Missing required parameter: 'input[n].output'

This is not usually a login failure. It means the openai-auth backend rejected the conversation history because one prior tool-result item was missing the required output field. Common causes are a saved/resumed session with an interrupted tool call, or an adapter history-conversion bug exposed by the stricter Responses/Codex payload validator.

Try, in order:

/redo

If that does not help, start a fresh session:

/clear

If you need the context from a large session, manually summarize the important state into the new prompt instead of replaying the full tool history. Re-running yottacode openai-auth login will not fix malformed session history.

--worktree exits with “workspace trust not accepted”

yottacode --worktree <name> requires the repo root to be trusted. Run yottacode once in the repo without --worktree, accept the trust prompt, then retry:

cd /path/to/repo
yottacode               # accept the trust prompt
# (Ctrl-C to exit when the TUI opens, or finish your session)
yottacode --worktree feature-x

Trust is persistent โ€” you only do this once per repo. See security-and-allow-lists.md.

Worktree from yottacode run --worktree wasn’t cleaned up

This is intentional. Oneshot / non-interactive runs cannot show a keep-or-remove prompt, so they leave the worktree in place. Remove it manually:

yottacode worktree remove <name>             # if clean
yottacode worktree remove <name> --force     # if dirty (discards uncommitted work)

yottacode worktree list shows everything under ~/.yottacode/worktrees/<repo-slug>/.

Reporting bugs

Include:

  • yottacode version
  • provider and model
  • yottacode doctor output, redacted
  • a minimal reproducer
  • exported session Markdown or JSONL if relevant: yottacode sessions export <id-or-name>