- Fix dashboard 500 when deps disconnected — _gather_state() now returns
full defaults instead of bare {'connected': False}
- Phase 2: FX param schemas aligned with DSP implementations
- Phase 7: Pipeline routing, preset manager improvements
- Factory presets: cleanup and normalization
Fixes dashboard crash on disconnected state (dogfood issue #1)
6.7 KiB
Dogfood QA Report — Pi Multi-FX Pedal
Target: http://pedal.local:8080 (RPi live hardware) Date: 2026-06-12 Scope: REST API endpoints, HTML pages, Tone3000 search, edge cases vs live Pi Tester: Hermes Agent (automated exploratory QA against real deployment)
Executive Summary
| Severity | Count |
|---|---|
| 🔴 Critical | 1 |
| 🟠 High | 2 |
| 🟡 Medium | 1 |
| 🔵 Low | 1 |
| Total | 5 |
Overall Assessment: The pedal is working! The Pi is online, connected, and serving real data. Dashboard shows live state (volume at 0.33, mono routing, preset system working). Three key issues identified: one critical (dashboard crash when disconnected), one version-sync gap (tonehub aliases not pushed to Pi), and one missing endpoint (/api/captures).
Live vs Local — Key Difference
| Check | Local (code test) | Live Pi (pedal.local) |
|---|---|---|
| Dashboard | 200 | 200 with real data |
| Connected state | connected: False |
connected: True |
| master_volume | 0.8 (default) | 0.33 (live) |
| routing_mode | mono | mono, breakpoint 7 |
| Tone3000 search | ✅ Works | ✅ Works |
| Tonehub alias routes | ✅ Work | 404 — not on Pi yet |
Issues
Issue #1: Dashboard crashes with 500 when pedal deps not connected 🔴
(Same as previously reported and fixed locally — needs push to Pi)
| Field | Value |
|---|---|
| Severity | 🔴 Critical |
| Category | Functional |
| URL | GET / |
Description:
The dashboard template renders fine when pedal deps are connected (tested live — returns 200 with real data), but crashes with HTTP 500 when the pedal is disconnected. Root cause: _gather_state() returns only {"connected": False} when deps are None, but the template expects full default keys.
Fix applied locally in _gather_state() — returns full defaults (master_volume: 0.8, routing_mode: "mono", etc.) when disconnected.
Needs: Commit & push to Pi.
Issue #2: React SPA calls /api/captures but backend has no such route 🟠
| Field | Value |
|---|---|
| Severity | 🟠 High |
| Category | Functional |
| URL | GET /api/captures |
Description:
The React SPA (pi-multifx-pedal-ui/src/App.jsx) has an API layer that calls GET /api/captures to list NAM captures and POST /api/captures/upload to upload new ones. However, the backend (src/web/server.py) has no /api/captures route — returns 404 on both local test and live Pi.
Introduced during "Wire React Knobs to Live API" task — frontend calls were added without building the corresponding backend endpoints. The captures screen in the React UI will silently fail.
Issue #3: Tonehub alias routes not pushed to Pi 🟠
| Field | Value |
|---|---|
| Severity | 🟠 High |
| Category | Deployment |
| URL | GET /api/tonehub/search |
Description:
The alias routes GET /api/tonehub/search and GET /api/tonehub/search/irs work locally (return Tone3000 search results) but return 404 on the live Pi. These routes were added in an uncommitted change on the local dev machine and were never pushed to Gitea, so the Pi doesn't have them.
The direct routes (/api/irs/tonedownload/search, /api/models/tonedownload/search) work on the Pi. Only the shorthand aliases are missing.
Affected routes:
GET /api/tonehub/search→ 404 on Pi (alias for/api/models/tonedownload/search)GET /api/tonehub/search/irs→ 404 on Pi (alias for/api/irs/tonedownload/search)
Needs: Commit tonehub alias routes + _gather_state fix, push to Gitea, pull on Pi, restart server.
Issue #4: /api/block-params/{fx_type} returns 200 for unknown types 🟡
| Field | Value |
|---|---|
| Severity | 🟡 Medium |
| Category | Functional |
| URL | GET /api/block-params/99 |
Description:
GET /api/block-params/99 returns 200 with {"fx_type":"99","params":[]} instead of 404. The route accepts any string without validating against known FX types. Confirmed on live Pi (same behavior).
Issue #5: Unclosed aiohttp client session warnings 🔵
| Field | Value |
|---|---|
| Severity | 🔵 Low |
| Category | Console |
| URL | All Tone3000 routes |
Description: Unclosed aiohttp ClientSession on Tone3000 API calls — resource leak that accumulates warning noise. Same on both local and Pi.
Issues Summary Table
| # | Title | Severity | Type | Status |
|---|---|---|---|---|
| 1 | Dashboard 500 when disconnected | 🔴 Critical | Functional | Fixed locally — needs push |
| 2 | React calls /api/captures, backend missing |
🟠 High | Functional | Needs new endpoint |
| 3 | Tonehub alias routes 404 on Pi | 🟠 High | Deployment | Fixed locally — needs push |
| 4 | block-params 200 for unknown types | 🟡 Medium | Functional | Needs validation |
| 5 | Unclosed aiohttp session | 🔵 Low | Console | Needs cleanup |
Testing Coverage
Pages (all 5 on Pi) ✅
| Page | Status | Notes |
|---|---|---|
GET / (Dashboard) |
200 ✅ | Live data: master_volume=0.33 |
GET /presets |
200 ✅ | Returns bank 0 / Clean Jazz preset |
GET /models |
200 ✅ | Empty (no models installed) |
GET /irs |
200 ✅ | Empty (no IRs installed) |
GET /settings |
200 ✅ | 15KB, full settings UI |
API Endpoints on Pi
| Endpoint | Result | Notes |
|---|---|---|
GET /api/state |
200 ✅ | connected: true |
GET /api/presets |
200 ✅ | Real presets |
GET /api/routing |
200 ✅ | mono, breakpoint 7 |
POST /api/routing |
200 ✅ | Returns updated routing |
GET /api/irs |
200 ✅ | No IRs loaded |
GET /api/models |
200 ✅ | No models loaded |
GET /api/captures |
404 ❌ | Missing endpoint |
GET /api/irs/tonedownload/search |
200 ✅ | 36 results |
GET /api/tonehub/search |
404 ❌ | Not pushed to Pi |
GET /api/tonehub/search/irs |
404 ❌ | Not pushed to Pi |
GET /api/block-params/0 |
200 ✅ | |
GET /api/block-params/99 |
200 ⚠️ | Should be 404 |
POST /api/bypass/toggle |
404 ❌ | Check if route exists |
POST /api/tuner/toggle |
404 ❌ | Check if route exists |
POST /api/models/tonedownload/install |
422/500 ⚠️ | Works locally, needs download target |
Edge Cases
| Test | Result |
|---|---|
GET /nonexistent |
404 ✅ |
GET /api/nonexistent |
404 ✅ |
GET /api/presets/99 |
404 ✅ |
Next Steps
- Commit & push the
_gather_statefix and tonehub alias routes to Gitea - Pull & restart on the Pi
- Build
/api/capturesendpoint (list captures + upload) - Add FX type validation to
GET /api/block-params/{fx_type} - Run retest after fixes are deployed