Minimal troubleshooting flow

Corresponding source

Troubleshooting layerSource to inspect first
Installation and commandpyproject.toml, nanobot/cli/commands.py
Configuration path and parsingnanobot/config/paths.py, nanobot/config/loader.py, nanobot/config/schema.py
Provider and modelnanobot/providers/registry.py, nanobot/providers/factory.py, nanobot/providers/base.py
Agent main pathnanobot/agent/loop.py, nanobot/agent/runner.py
Log directorynanobot/config/paths.py::get_logs_dir, nanobot/utils/logging_bridge.py
Peripheral runtime surfacesnanobot/channels/, nanobot/api/server.py, nanobot/gateway/, nanobot/webui/

Learning objective

When “nanobot does not work,” use the shortest path to identify the failing layer instead of inspecting every module at once.

Prerequisites

  • Complete one DeepSeek configuration.
  • Run the CLI with --logs.
  • Use rg.

Overall diagnostic order

flowchart TD
    A["Does the command start?"] -->|No| I["Installation / Python / entry point"]
    A -->|Yes| B["Does configuration load?"]
    B -->|No| C["JSON / environment variables / Pydantic validation"]
    B -->|Yes| D["Can the Provider be created?"]
    D -->|No| E["preset / provider / model / apiBase"]
    D -->|Yes| F["Does a minimal CLI request respond?"]
    F -->|No| G["Authentication / upstream error / timeout / AgentRunner"]
    F -->|Yes| H["Inspect only the failing entry point or subsystem"]

Layer 1: Installation and command

python --version
python -m pip show nanobot-ai
nanobot --version
python -m nanobot --version

If the module form works but nanobot does not, the problem is usually the virtual environment or command entry point, not AgentLoop.

Layer 2: Configuration parsing

Check:

  • whether the JSON is valid;
  • which --config is active;
  • which --workspace is active;
  • whether ${DEEPSEEK_API_KEY} exists;
  • whether the preset name matches agents.defaults.modelPreset;
  • whether the current schema accepts the chosen camelCase or snake_case fields.

In PowerShell, check only whether the key exists; do not print it:

if ([string]::IsNullOrWhiteSpace($env:DEEPSEEK_API_KEY)) {
    "DEEPSEEK_API_KEY is not set"
} else {
    "DEEPSEEK_API_KEY is set"
}

Layer 3: Provider resolution

Related source:

Config.resolve_preset
  → providers/factory.py::_make_provider_core
  → providers/registry.py::ProviderSpec
  → OpenAICompatProvider

Check:

  • whether the preset explicitly selects deepseek;
  • whether the model name is currently available;
  • whether the DeepSeek configuration block exists;
  • whether apiKey was resolved;
  • whether an incorrect apiBase was set accidentally.

Layer 4: Minimal CLI Turn

Use the fewest peripheral components:

nanobot agent `
  --config $nanobotConfig `
  --workspace $nanobotWorkspace `
  --logs `
  --message "Reply with OK"

If this fails, do not start:

  • Gateway;
  • Channel;
  • WebUI;
  • Cron;
  • MCP.

Layer 5: Model request and Runner

Classify the error:

ErrorLikely layer
401/403key, permissions, Provider endpoint
402account balance
422model name or request arguments
429rate limit
500/503Provider service
LLM timeoutnetwork, upstream response, NANOBOT_LLM_TIMEOUT_S
stream idle timeoutstream produced no event for too long, NANOBOT_STREAM_IDLE_TIMEOUT_S
empty final responseempty model response or finalization branch
tool_errorTool lookup, validation, execution, or security boundary
max iterationsmodel-tool loop did not terminate normally

Layer 6: Inspect only the added perimeter

After the minimal CLI succeeds:

API failure

Check:

  • HTTP body;
  • multipart handling;
  • session_id;
  • API session lock;
  • SSE;
  • api/server.py.

Channel failure

Check:

  • whether the Channel is enabled;
  • allowFrom;
  • Pairing;
  • whether ChannelManager started successfully;
  • whether the inbound message was published;
  • whether the outbound dispatcher sent the response.

WebUI failure

Check:

  • WebSocket Channel;
  • whether Gateway is running;
  • RuntimeEventBus;
  • WebuiTurnCoordinator;
  • browser connection and token;
  • UI rendering before changing AgentRunner.

Cron or Heartbeat failure

Check:

  • whether Gateway remains running;
  • whether the workspace is correct;
  • <workspace>/cron/jobs.json;
  • Heartbeat configuration and template;
  • whether an active session delayed the job.

Log locations

nanobot/config/paths.py::get_logs_dir() resolves the log directory to logs/ under the directory containing the current config. Not every startup mode writes the same log file, however; CLI --logs primarily controls whether runtime logs are displayed.

Distinguish:

  • console logs;
  • the instance logs/ directory;
  • Channel/WebUI logs;
  • errors returned by the third-party Provider.

Narrow the scope with tests

Set-Location "example\nanobot\code-EN"
 
pytest tests/agent/test_loop_runner_integration.py -q
pytest tests/agent/test_runner_errors.py -q
pytest tests/providers -q

Passing tests do not prove that a real key or network works. They prove only that the tested local contract did not fail.

One-page checklist

  • Python 3.11+
  • The current virtual environment has an editable install of the local source
  • --config is explicit
  • --workspace is explicit
  • The environment variable exists, but its value was not printed
  • Preset, Provider, and model agree
  • A minimal CLI request was tested
  • --logs is enabled
  • The complete error type and failing layer were recorded
  • API, Channel, WebUI, or Cron was inspected only after the core succeeded

Next step

Continue to the One Turn learning path.