Minimal troubleshooting flow
Corresponding source
| Troubleshooting layer | Source to inspect first |
|---|---|
| Installation and command | pyproject.toml, nanobot/cli/commands.py |
| Configuration path and parsing | nanobot/config/paths.py, nanobot/config/loader.py, nanobot/config/schema.py |
| Provider and model | nanobot/providers/registry.py, nanobot/providers/factory.py, nanobot/providers/base.py |
| Agent main path | nanobot/agent/loop.py, nanobot/agent/runner.py |
| Log directory | nanobot/config/paths.py::get_logs_dir, nanobot/utils/logging_bridge.py |
| Peripheral runtime surfaces | nanobot/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 --versionIf 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
--configis active; - which
--workspaceis 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
→ OpenAICompatProviderCheck:
- whether the preset explicitly selects
deepseek; - whether the model name is currently available;
- whether the DeepSeek configuration block exists;
- whether
apiKeywas resolved; - whether an incorrect
apiBasewas 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:
| Error | Likely layer |
|---|---|
| 401/403 | key, permissions, Provider endpoint |
| 402 | account balance |
| 422 | model name or request arguments |
| 429 | rate limit |
| 500/503 | Provider service |
| LLM timeout | network, upstream response, NANOBOT_LLM_TIMEOUT_S |
| stream idle timeout | stream produced no event for too long, NANOBOT_STREAM_IDLE_TIMEOUT_S |
| empty final response | empty model response or finalization branch |
| tool_error | Tool lookup, validation, execution, or security boundary |
| max iterations | model-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 -qPassing 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
-
--configis explicit -
--workspaceis explicit - The environment variable exists, but its value was not printed
- Preset, Provider, and model agree
- A minimal CLI request was tested
-
--logsis 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.