Troubleshooting

Start with these commands:

school-bell /home/pi/schema.json --check
systemctl status school-bell.service
journalctl -u school-bell.service -n 100 --no-pager
timedatectl status

Configuration errors

Pydantic reports the complete nested path of invalid fields. Correct every reported error and rerun --check. Unknown fields are rejected; do not remove one without confirming whether it is a misspelling. config_hash and schedule_hash are generated values and must not appear in the JSON.

Service does not start

Confirm that the systemd ExecStart path, configuration path and service user match the installation. Check that the virtual environment uses Python 3.11 or newer:

/home/pi/.local/bin/python --version
/home/pi/.local/bin/school-bell --version

Audio is silent

Verify the file and ALSA device outside School Bell, then use --test only when activating the real output is safe:

aplay -l
aplay -L
aplay /home/pi/samples/bell.wav
school-bell /home/pi/schema.json --test

See Audio and ALSA for device selection, mixers and multi-zone examples.

GPIO does not switch

Check BCM pin numbering, relay polarity, power and service-user permissions. Active-low relay boards require "buzz_active_high": false for legacy outputs or "active_high": false on each key-specific relay. Also confirm that the requested WAVE key occurs in the relay’s wav_keys. Never diagnose relay wiring with a live high-voltage or bell circuit attached. The pin-number explanation, Waveshare mapping and safe test sequence are in GPIO, relays and manual button.

Bells ring at the wrong time

Check all three sources of time information:

date --iso-8601=seconds
timedatectl status
grep timezone /home/pi/schema.json

The system clock must be synchronized and timezone must match the intended local schedule. See Networking and time synchronization for behavior during NTP outages.

Monitoring is missing

Local scheduling can be healthy even when monitoring is unavailable. Check DNS, routing, firewall rules, syslog protocol and port, then inspect local journal events. For HTTP status, verify the bind address and token as described in Remote monitoring.

Remote trigger fails

For SSH, test key authentication as the School Bell service user and confirm the remote command. For webhooks, verify TLS at the reverse proxy, the bearer token, request body and rate limit. A failed remote manual action should not delay or change its local bell action. Follow the end-to-end checks in Remote bells and webhooks.

If curl trusts a local HTTPS webhook but School Bell reports SSLError, the virtual environment may be using a different CA bundle. Configure REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt in a systemd drop-in after installing the private CA in the operating-system trust store. Also remove the backend :8081 port from an HTTPS remote URL; Caddy listens on the default HTTPS port 443.

Calendar data is unavailable

Run --check to test OpenHolidays and iCalendar parsing. Verify DNS, TLS, proxy and firewall access. Calendar URLs may contain secrets and are therefore redacted from normal errors; test them carefully without publishing them in logs or issue reports. Holidays and calendar exceptions describes refreshes, cached data and the fail-open behavior when no valid data is available.