Skip to content

Troubleshooting

Troubleshooting pages should start from symptoms and end with verification. Avoid broad speculation when a concrete command can show the state.

Before diving into specific issues, run these commands to gather context:

Terminal window
# Verify foxctl is installed and reachable
foxctl version
# Check Go version (for building from source)
go version
# Show current configuration
foxctl config show

Capture stderr for debugging — structured logs (zerolog JSON) are written to stderr, while Protocol v1 envelopes go to stdout:

Terminal window
foxctl run fs/ls --input '{"path":"."}' 2>debug.log

All foxctl errors use structured error codes in the envelope’s error.code field:

CodeMeaningCommon Causes
EARGInvalid argumentMissing or malformed parameters
ENOTFOUNDResource not foundSkill, file, or digest doesn’t exist
ETIMEOUTOperation timed outNetwork issues, long-running skill
ERUNTIMERuntime errorSkill crashed or panicked
EENVELOPEEnvelope validation failedMalformed JSON, missing fields
EPARSEParse errorInvalid input format
EPOLICYPolicy violationPath traversal, network access denied
EIOI/O errorFile access failure, CAS corruption
EAUTHAuthentication failedInvalid credentials
ERATELIMITRate limit exceededToo many API calls
ECANCELEDOperation canceledUser cancellation, context timeout

The binary is not in your PATH or is not installed.

Terminal window
# If built from source, add to PATH
export PATH="$PATH:/path/to/foxctl/bin"
# Or install to a standard location
sudo cp ./foxctl /usr/local/bin/
# Verify
which foxctl
foxctl version

If foxctl on PATH reports Command 'run' not available in bundled mode, you are running a wrapper from another install. Run ./bin/foxctl from the repo checkout instead, or rebuild with make build.

Terminal window
chmod +x ./foxctl

macOS: “foxctl is damaged and can’t be opened”

Section titled “macOS: “foxctl is damaged and can’t be opened””

Gatekeeper is blocking the binary.

Terminal window
xattr -d com.apple.quarantine ./foxctl

Or build from source to avoid the issue entirely:

Terminal window
make build

You are not in the repository root:

Terminal window
cd /path/to/foxctl
make build

Missing or outdated dependencies:

Terminal window
go mod download
go mod tidy
make build

foxctl requires pure Go builds. Always set CGO_ENABLED=0:

Terminal window
CGO_ENABLED=0 make build

Do not revive the legacy CGO/SQLite storage lane (no -tags=libsqlite3, no foxctl-cgo, no sqlite-vector). Turso is the canonical SQLite-family storage path.

Install the linter:

Terminal window
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
Terminal window
go mod download
go test ./...

The skill is not installed or not in the skill path.

Terminal window
# List installed skills
foxctl skills list
# Build and install all skills
make skills-install
# Build a single skill
CGO_ENABLED=0 go build -o ~/.foxctl/skills/code/symbols/bin ./skills/code_symbols

Important: The skill loader looks for a binary named bin (or bin-cgo), not a custom name. Always use the correct output path:

Terminal window
# Correct — loader will find it
go build -o ~/.foxctl/skills/my/skill/bin ./skills/my_skill
# Wrong — loader won't find it
go build -o ~/.foxctl/skills/my/skill/my_skill ./skills/my_skill

Skills must also be installed after building — the build step creates the binary in the source directory, but the loader searches ~/.foxctl/skills/:

Terminal window
# Install all skills
make skills-install

You attempted to access a file outside the workspace boundary:

Terminal window
# Check current workspace
foxctl config show | grep workspace
# Use relative paths within workspace
foxctl run fs/read --input '{"path":"./src/main.go"}'

The skill crashed or encountered an internal error:

Terminal window
# Check stderr for details
foxctl run <skill> 2>error.log
cat error.log
# Enable debug logging
export FOXCTL_LOG_LEVEL=debug
foxctl run <skill>
# Check skill manifest for requirements
foxctl skills describe <skill>

WASI skills run in a sandboxed environment with no network access (network: "none"). If a skill needs network access, use an exec skill instead.

Rebuild WASI skills from source:

Terminal window
make skills-build

The default timeout is 5 minutes. For long-running operations, use the jobs system:

Terminal window
foxctl jobs submit <skill> --args '...'
foxctl jobs tail <job-id>

Skills must explicitly load .env files. Add config.LoadDotEnv() before any os.Getenv() calls:

import "github.com/joshka0/foxctl/internal/platform/config"
func main() {
config.LoadDotEnv() // BEFORE os.Getenv()
apiKey := os.Getenv("FOXCTL_EMBEDDING_API_KEY")
}
Terminal window
# Check job queue
foxctl jobs list --status queued
# Submit a simple test job to verify the queue is processing
foxctl jobs submit fs/ls --path .

Crash recovery may not have triggered:

Terminal window
# Cancel the stuck job
foxctl jobs cancel <job-id>
# Last resort: direct database update
sqlite3 ~/.foxctl/foxctl.db "UPDATE jobs SET status='error' WHERE id='<job-id>';"
Terminal window
# Check job status
foxctl jobs get <job-id>
# If it errored, check stderr
foxctl jobs get <job-id> --show-stderr
# Check if the CAS artifact still exists
foxctl cas list | grep <digest>

Memory queries are scoped by workspace path. Run from the correct project directory or specify the workspace explicitly:

Terminal window
# Run from project directory
cd /path/to/project
foxctl memory search "auth"
# Or specify workspace in the skill input
foxctl run memory/query --input '{"workspace": "/path/to/project"}'

The repo graph index may be missing, empty, or stale. Check index status before judging search quality:

Terminal window
foxctl index repo status --workspace /path/to/repo

If nodes_total is 0 or index_matches_head is false, rebuild the index for the repo’s languages:

Terminal window
foxctl index repo build --workspace /path/to/repo --go=false --typescript

Mixing embedding providers with different vector dimensions causes search failures. Use the same provider for storage and queries:

ProviderDimensions
Qwen3 Embedding 8B4096
Qwen3 Embedding 4B2560
Qwen3 Embedding 0.6B1024
Gemini3072

If you switch providers, rebuild the affected vector store.

A CAS artifact may be corrupted:

Terminal window
# Delete the corrupted artifact
foxctl cas delete <digest> --force
# Re-run the operation to regenerate it
foxctl run <skill> --cache off
Terminal window
# Check total CAS usage
du -sh ~/.foxctl/cas/
# List unpinned artifacts
foxctl cas list --unpinned
# Dry-run garbage collection
foxctl cas gc --older-than 168h --dry-run
# Run garbage collection
foxctl cas gc --older-than 168h --confirm
# Pin important artifacts before GC to protect them
foxctl cas pin <digest>

SQLite has limited concurrency. If you see locking errors:

Terminal window
# Remove stale lock files
rm -f ~/.foxctl/foxctl.db-shm ~/.foxctl/foxctl.db-wal
# If persistent, backup and vacuum
cp ~/.foxctl/foxctl.db ~/.foxctl/foxctl.db.bak
sqlite3 ~/.foxctl/foxctl.db "VACUUM;"
Terminal window
# Check integrity
sqlite3 ~/.foxctl/foxctl.db "PRAGMA integrity_check;"
# Restore from backup if available
cp ~/.foxctl/foxctl.db.bak ~/.foxctl/foxctl.db
# Or rebuild from scratch (loses history)
rm ~/.foxctl/foxctl.db
foxctl config init
Terminal window
# Check agent status
foxctl agent info <agent-id>
# Stream live events
foxctl agent watch <agent-id>
# Send a follow-up and wait
foxctl agent ask <agent-id> --question "What is your current state?" --wait --timeout 120s

Room messages stored but not visible in tmux

Section titled “Room messages stored but not visible in tmux”

Check all three layers — workspace alignment, room membership, and pane delivery:

Terminal window
# 1. Verify the live loop is in the correct workspace
ps -Ao pid=,command= | rg 'foxctl room loop'
lsof -a -p <loop-pid> -d cwd
# 2. Check room membership includes the pane
foxctl room show <room-id> --workspace /path/to/workspace
# 3. Read the pane directly
foxctl mux read <pane-id> --lines 120

For tmux-backed room relay, pane_id is the actual delivery target. actor_id is for room semantics and matching.

foxctl sets resource limits for safety. Run as a regular user (not root):

Terminal window
# Check current ulimits
ulimit -a

Use forward slashes in foxctl inputs, even on Windows:

Terminal window
foxctl run fs/read --input '{"path":"./src/main.go"}'

.env file not loading in sandboxed environments

Section titled “.env file not loading in sandboxed environments”

If ~/.foxctl/.env is a symlink to the repo’s .env and the repo path doesn’t exist in the sandbox, the symlink breaks. Use a real file:

Terminal window
make env-sync # Copies repo .env → ~/.foxctl/.env
# Verify it's a real file (not a symlink)
ls -la ~/.foxctl/.env

The .env loader checks these locations in order:

  1. ~/.foxctl/.env (global defaults)
  2. $FOXCTL_HOME/.env (if set)
  3. $PWD/.env (project overrides)
Terminal window
export FOXCTL_LOG_LEVEL=debug
foxctl run <skill> 2>debug.log
Terminal window
# Pretty-print the JSON envelope
foxctl run fs/ls --input '{"path":"."}' | jq .
# Check specific fields
foxctl run fs/ls --input '{"path":"."}' | jq '.meta'
Terminal window
# These exercise core functionality without skill-specific logic
foxctl run fs/ls --input '{"path":"."}'
# If these fail, the issue is in core — not in a specific skill
Terminal window
# Backup first
cp -r ~/.foxctl ~/.foxctl.bak
# Remove all state
rm -rf ~/.foxctl/
# Reinitialize
foxctl config init
foxctl skills list # Should be empty
PitfallSolution
Running from wrong directoryRun from repository root or specify workspace paths
Skills not found after buildRun make skills-install to install to ~/.foxctl/skills/
Stale cache returning old resultsUse --cache off to bypass cache
Secrets in command historyUse environment variables, not CLI arguments
Expecting network from WASI skillsWASI enforces network: "none" — use exec skills for network access
Wrong foxctl binary on PATHUse ./bin/foxctl from the repo checkout
Observability not workingUse absolute paths in FOXCTL_OBS_DIR, not ~ shorthand

Before reporting an issue:

  1. Check this troubleshooting guide and Gotchas
  2. Enable debug logging: export FOXCTL_LOG_LEVEL=debug
  3. Try a minimal reproduction — simplify to the smallest failing case
  4. Check if it worked before — what changed?

When opening an issue, include:

Terminal window
# System info
uname -a
go version
foxctl version
# Reproduction with debug output
foxctl run <skill> --input '{}' 2>error.log
cat error.log