Skip to content

Troubleshooting

Start with the logs. From ~/ambrogio, read the backend’s with docker compose logs backend; from the satellite’s folder, docker compose logs satellite. Logs lists the events.

When the backend refuses to start, it writes Unable to start HTTP server. to standard error and, just before it, one JSON line on standard output that says why:

Terminal window
docker compose logs backend | grep server_startup_failed
{"level":50,...,"event":"server_startup_failed","err":{"type":"ProjectError","message":"Invalid agent configuration: general",...},"msg":"Server startup failed"}

Look at err.message and find it in this table.

err.message What to check
Missing environment variable <NAME> A required variable is not set, or is set to an empty string. In production AMBROGIO_ENV, AMBROGIO_HTTP_HOST, AMBROGIO_HTTP_PORT, AMBROGIO_PUBLIC_HTTPS and AMBROGIO_DATABASE_URL are required; with voice, each listed language needs its profile variables. docker compose config shows the variables Compose passes to the container.
Invalid environment variable <NAME>: <condition> The variable has a value the backend does not accept; the condition says what it expects. Common cases: AMBROGIO_ENV other than development, test or production; a port outside 1–65535; AMBROGIO_PUBLIC_HTTPS other than true or false; AMBROGIO_HSTS_MAX_AGE_SECONDS missing with AMBROGIO_PUBLIC_HTTPS=true; an origin with a path, a trailing slash or *; a database URL without a user or a password, or with ? or #; AMBROGIO_LANGUAGE other than en or it; a time zone that is not an IANA name such as Europe/Rome; AMBROGIO_LIST_PAGE_SIZE above AMBROGIO_MAX_LIST_PAGE_SIZE; AMBROGIO_VOICE_LANGUAGES without AMBROGIO_LANGUAGE or with an unknown or repeated language.
Conversation archive could not be prepared The backend could not use the database of AMBROGIO_DATABASE_URL: PostgreSQL is not running or not reachable from the backend, the database does not exist, the user or password is wrong, the user cannot create tables, or the database structure could not be updated. Check docker compose logs database.
Voice resources are unavailable A folder of the active voice profile lacks the files listed in Backend configuration. Check the path and the mount.
Voice components could not be loaded The files are there but a model failed to load. Download it again.
Agent configuration directory unavailable The agents folder, AMBROGIO_AGENTS_DIR or /etc/ambrogio/agents by default, does not exist. Check the mount of ./agents in compose.yaml.
Missing orchestrator configuration There is no orchestrator.json.
No specialist agent configured There is no agent file besides orchestrator.json.
Invalid agent configuration filename: <file> The name must be lowercase letters, digits and hyphens, starting with a letter.
Missing environment variable <NAME> for agent <id> The variable named by apiKeyEnv, tokenEnv or clientSecretEnv in that agent’s file is not set in the backend environment. Add it to the environment section of the backend service and its value to .env.
Invalid agent configuration: <id> That agent’s file: check that it is valid JSON and that every field follows Agent configuration. A common mistake is a literal apiKey, token or clientSecret: name the variable with apiKeyEnv, tokenEnv or clientSecretEnv instead.
Invalid agent options: <id> llm.options may contain only temperature (0 or more) and max_tokens (1 or more).
HTTP listener could not start The port is already in use, or AMBROGIO_HTTP_HOST is not an address of this machine.

For errors that come from outside Ambrogio (a library, the network, the operating system), the line shows only the step that failed, not the original message, so no secret can end up in the log.

Backend configuration and Agent configuration list every rule.

The backend starts without waiting for MCP servers. Right after it starts listening, it connects once to the MCP server of each agent that has one. If that attempt fails, the agent stays unavailable until the backend restarts, and the log has one agent_mcp_unavailable line for it. The other agents keep working. A request that the orchestrator gives to an unavailable agent gets the standard error answer, “I can’t complete the response.”, and the log has conversation_reply_failed with the cause Agent unavailable: <id>.

The reason field of agent_mcp_unavailable says what went wrong:

reason Cause
connection_failed The backend could not connect to the agent’s MCP server or list its tools or prompts. Test mcp.url from the backend host (in Docker, localhost is the container), and check the token or OAuth settings.
tool_unavailable The name in the tool field is in the agent’s mcp.tools but not among the tools of its MCP server. Names are case-sensitive and must be written as the server declares them. They can change when the server is updated: Home Assistant 2025.12.5 declared HassTurnOn and GetLiveContext, Home Assistant 2026.10.4 declares intent__HassTurnOn and homeassistant__GetLiveContext.

The backend does not try again. After fixing the cause, or once the MCP server is reachable again, restart the backend.

  • Check the address from the same computer: curl http://ambrogio.home.lan:3000/api/v1/conversations.
  • The client refuses addresses with a user name, password, query string or #fragment.
  • If the list loads but sending a message fails, the WebSocket on /api/session is being blocked. Behind a proxy, check that it forwards upgrades; see Put the backend behind HTTPS.
  • A backend built from a commit older than the ambrogio.v1 protocol cannot hold a session with the current client. Use a release, or a commit from 58b0df4 onwards; see Versions and compatibility.

The client needs at least 70 columns and 14 rows. Make the window bigger; your conversation is kept.

Conversations explains what each state means.

The backend accepted the turn and has not saved an outcome yet. Press Ctrl+R later to refresh. If it never changes, the backend probably stopped while answering; after the next restart the turn shows as interrupted.

Every answer is “I can’t complete the response.”

Section titled “Every answer is “I can’t complete the response.””

This is the standard message for a turn that failed after it was accepted. Common causes:

  • the provider’s API key is wrong, out of credit, or rate-limited;
  • the orchestrator’s model does not support structured JSON output, or the model of an agent with tools does not support tool calling; see Providers;
  • the answer took longer than 30 seconds;
  • an agent with tools needed more than its maxToolCalls;
  • the orchestrator chose no valid agent.

The backend log has a conversation_reply_failed event for each of these.

The satellite exits with invalid_configuration

Section titled “The satellite exits with invalid_configuration”

The satellite checks its environment variables before it starts and stops at the first problem. The log line names the variable and the problem, never its value:

{"level":"info","time":...,"event":"invalid_configuration","variable":"AMBROGIO_WAKE_WORD","condition":"invalid"}
  • "condition":"missing": set the variable. AMBROGIO_ENV and AMBROGIO_BACKEND_URL are always required, and the three AMBROGIO_ATTENUATION_* variables go together.
  • "condition":"invalid": correct the value following the rules of that variable in Satellite configuration.

invalid_arguments means the command line had arguments: the satellite takes none.

When the satellite cannot start, it prints Unable to start Ambrogio satellite. to standard error and writes one satellite_startup_failed line. Its err.message says which step failed:

err.message What to check
Wake word model could not be loaded The keyword spotting model is missing or damaged. If you mount your own model at /app/models/kws, check its files; see Change the wake word. Otherwise reinstall the satellite or pull the image again.
Voice activity model could not be loaded The bundled speech detection model is damaged. Reinstall the satellite or pull the image again.
Microphone could not be started The selected microphone does not exist or is busy. See Choose audio devices.

Lines on standard error that start with /shared/sherpa-onnx/ come from the speech library, not from the satellite.

When two things fail, for example the microphone and then the release of a model, err.type is LifecycleError and err.faults lists both.

The satellite plays this error tone in two cases. Its log tells you which:

  • satellite_failure: the interaction failed on the satellite’s side. The backend cannot be reached, the session dropped during the turn, or no outcome arrived within 60 seconds. Check the address and the network from the device, then the backend logs. The satellite keeps running and tries again at the next wake word.
  • satellite_voice_unavailable: the backend is running without voice and answered in text. Configure voice on the backend.

The satellite never reacts to the wake word

Section titled “The satellite never reacts to the wake word”
  • Check that the microphone works: arecord -d 5 test.wav && aplay test.wav.
  • Make sure the satellite uses the right microphone; see Choose audio devices.
  • Say the word set in AMBROGIO_WAKE_WORD, Alexa unless you changed it.
  • If the log shows satellite_wake_rejected when you say it, the word was spotted but the speech detector heard no speech around it. Check the microphone level and speak towards the device.
  • If the log shows nothing, lower AMBROGIO_WAKE_WORD_THRESHOLD a little, for example to 0.2.
  • The bundled model is trained on English speech. If your word does not sound English, try another one; see Change the wake word.

Every wake-up writes a satellite_wake_detected line. A detection without speech around it, for example from a noise, is discarded and writes satellite_wake_rejected instead, without waking the satellite. So a false wake-up happens when the keyword spotter reacts while someone, or a TV, is speaking.

  • Raise AMBROGIO_WAKE_WORD_THRESHOLD a little, for example to 0.3.
  • Try another wake word: how well a word is recognised, false wake-ups included, depends on the word. See Change the wake word.
  • Move the device away from the TV.

The satellite plays the beep once the backend session is ready. If the speaker cannot play it, the log shows satellite_ready_cue_failed and the satellite listens anyway. Check the speaker selector.

Speak without long pauses: a short silence ends the request, and a request may last at most 60 seconds. See Limits and timeouts.

Voice answers start long after I stop speaking

Section titled “Voice answers start long after I stop speaking”

If the delay grows with the length of what you say, the backend’s CPU cannot recognise speech in real time.

  1. Check that the backend host has AVX2:

    Terminal window
    grep -o -m1 avx2 /proc/cpuinfo
  2. If it prints nothing, run the backend on a CPU that meets the voice requirement.