2
Troubleshooting
MichalZaniewicz edited this page 2026-09-10 14:25:42 +02:00

Troubleshooting

A change I made was not picked up

The core is pulled from GitHub and cached. After editing the ref: in waveshare-va.yaml (or after a new release), clear the cache before building:

esphome clean waveshare-va.yaml
esphome run   waveshare-va.yaml

In the dashboard: Clean Build Files, then Install. Skipping this is the single most common reason a build seems unchanged.

The device does not come back after flashing

Right after an OTA reboot, the API port is closed for a few seconds while the device boots. That is normal. Give it up to a minute.

If it never returns and pings but refuses the API port, or you see repeated resets, it is crash-looping. Read on.

Boot loop, safe mode, or "OTA rollback detected"

The firmware has two safety nets:

  • Safe mode: after several failed boots in a row the device boots a minimal safe mode (Wi-Fi and OTA only) so you can flash a fix. The log says SAFE MODE IS ACTIVE.
  • OTA rollback: if a freshly flashed image resets before the boot is marked successful, ESP-IDF automatically reverts to the previous working image. The log says OTA rollback detected.

Both mean the new firmware crashed early. To recover and diagnose:

  1. Flash a known-good build. Over USB is most reliable, and it also gives you the serial boot log.
  2. Watch the serial console during boot and look for Guru Meditation Error, abort() or a Backtrace: line just before the reset. That names the cause.

If you customised the config, the usual culprits are actions that run during setup before their components exist (for example a select or switch trigger that touches the LED ring or the voice assistant at boot). Guard such triggers with the firmware's init_in_progress flag so they only run after on_boot.

Wake word is detected but nothing happens

  • The most common cause: no Assist pipeline is assigned. On the device page in Home Assistant, choose Configure and pick a pipeline.
  • If you added a standalone boot announcement, note that playing one at boot can leave the media player stuck "announcing", after which a wake word only stops that phantom announcement. This firmware avoids it by playing the boot chime only after the mic is clocking; do not move that logic earlier.
  • If the device reaches STREAMING_MICROPHONE and then stalls with no Starting STT by VAD line, see Stuck in STREAMING_MICROPHONE, speech-to-text never starts.

Stuck in STREAMING_MICROPHONE, speech-to-text never starts

Symptom: the wake word is detected, the chime plays, the microphone starts and the device reaches STREAMING_MICROPHONE, then stalls. Starting STT by VAD and STT by VAD end never appear in the log. The session ends only on a second wake word or on the Home Assistant pipeline timeout (around five minutes).

Two unrelated causes produce a near-identical log. Rule out the first before touching the second.

Home Assistant is HTTPS-only and the device cannot fetch audio

If Home Assistant is served over HTTPS on port 8123 with a certificate that covers a public domain (a DuckDNS or Let's Encrypt hostname, say) but not the LAN address the device connects to, every announcement and text-to-speech fetch fails certificate verification. The pipeline never completes, so the device holds in STREAMING_MICROPHONE. The signature in the device log is:

esp-x509-crt-bundle: Failed to verify certificate
esp-tls-mbedtls: mbedtls_ssl_handshake returned -0x3000
HTTP_CLIENT: Connection failed, sock < 0

The media player validates the server certificate against a bundled CA set and cannot accept a certificate issued for a hostname while it is reaching Home Assistant by bare IP.

Give the device a plain-HTTP path to Home Assistant:

  • Set the Home Assistant Internal URL (Settings, System, Network) to http://<home-assistant-ip>:8123 and leave the built-in HTTP server unencrypted.
  • If the local network must use HTTPS, terminate TLS at a reverse proxy (the Nginx Proxy Manager add-on, for example) and keep the Home Assistant http: server plain behind it.

Once the device can reach Home Assistant over plain HTTP the whole round trip works: chime, streaming, speech-to-text, response.

End-of-speech detection (VAD) closes the stream late or never

End of speech is decided on the device by the vad model under micro_wake_word, not by Home Assistant. The v1.0.0 defaults (probability_cutoff: 0.50, sliding_window_size: 5) are not reliable in every room: depending on the noise floor they either cut a speaker off after a short pause, or never fall below the threshold and hold the stream open until the Home Assistant timeout.

Looser values are on the beta branch (probability_cutoff: 0.3, sliding_window_size: 10). To try them, set ref: beta in the packages: block, run Clean Build Files, then Install.

Wake word is never detected

  • Check Microphone Mute is off.
  • Raise Wake word sensitivity.
  • Speak the wake word clearly: alexa or okay_nabu.
  • Confirm the mic came up in the boot log (ES7210 audio ADC). If it did not, see the cold-boot note in Hardware.

Playback is noise or static

On the stock config this should not happen. If you changed the audio section, the mic must stay pinned to 16-bit: as the I2S master it sets the frame width, and a 32-bit frame against the 16-bit DAC plays back as noise. See Audio architecture.

A faint hiss at boot

The amplifier is gated off until the first playback for exactly this reason. A hiss before any sound has played usually means the amp gating was changed; the amp_enable switch should be ALWAYS_OFF at boot and turned on by the media player on_state.

A Pulse effect shows a steady colour instead of pulsing

Its update_interval is shorter than its transition. Set update_interval to roughly twice transition_length. The bundled effects are already tuned.

Cannot flash over USB

  • Hold BOOT while plugging the board in to force download mode.
  • Make sure nothing in your config drives expander pins EXIO6 or EXIO7; driving them can disable USB. A camera left in the DVP connector can also block boot (it sits on strapping pins).

Getting logs

Use the ESPHome dashboard log view, or stream over the native API with scripts/esplog.py from the repository, which reads the API key from secrets.yaml and is better for catching boot-time races than the dashboard view. For a crash backtrace, use the USB serial console.