# SDK mismatch & missing-symbol crash – PocketDungeon July 16 2026 ## Symptom Board `192.168.68.112` on `{"cpuFamily":"esp32s3","osVersion":"0.8.0-dev"}` shows error dialog: ``` Error Application failed to start: missing symbol [OK] ``` Screenshot via `curl http://192.168.68.112/api/screenshot -o /tmp/shot.png` -> PNG 320x240 palettized. ## Root cause (2-fold) 1. **SDK / OS version mismatch** - `manifest.properties` said `sdk=0.7.0-dev` - Board runs `0.8.0-dev` (checked `GET /info` and `GET /api/screenshot` header) - Compiled against `0.7.0-dev-esp32s3/TactilitySDK` but device exports differ. 2. **Unexported LVGL style API used** - Code added for less-cramped QVGA intro used: - `lv_obj_set_style_max_width(...)` -> **NOT exported** in 0.7 nor 0.8 (verified via grep firmware `ESP_ELFSYM_EXPORT` / `DEFINE_MODULE_SYMBOL`) - `lv_obj_set_scrollbar_mode(...)` -> version-dependent / not reliably exported - Header exists in SDK's vendored LVGL, so it compiles, but loader fails at runtime. - `check_symbols.py` pattern: ```bash source $IDF_PATH/export.sh && xtensa-esp32s3-elf-nm -D build/.../*.app.elf | grep " U " grep -R "ESP_ELFSYM_EXPORT\|DEFINE_MODULE_SYMBOL" firmware/ ``` - Found exactly 1 missing: `lv_obj_set_style_max_width`. ## Fix checklist 1. **Query board version first** ```bash curl -s http://192.168.68.112:6666/info curl -s http://192.168.68.112/api/screenshot -o /tmp/intro.png ``` 2. **Bump manifest to match board** ```properties [manifest] version=0.1 [target] sdk=0.8.0-dev platforms=esp32,esp32s3,esp32c6,esp32p4 ``` 3. **Avoid unexported LVGL** Replace `set_style_max_width` with fixed percents: ```cpp // BAD (unexported) lv_obj_set_style_max_width(obj, 220, LV_PART_MAIN); // GOOD – gives side gutters on 320px QVGA lv_obj_set_width(card, LV_PCT(92)); lv_obj_set_width(btn, LV_PCT(80)); lv_obj_set_width(exitBtn, LV_PCT(70)); ``` For scroll: ```cpp // BAD lv_obj_set_scrollbar_mode(area, LV_SCROLLBAR_MODE_AUTO); // GOOD – default scroll works, add flag explicitly lv_obj_add_flag(scrollArea, LV_OBJ_FLAG_SCROLLABLE); ``` 4. **Rebuild with correct SDK** ```bash export TACTILITY_SDK_PATH=/Users/adolforeyna/Projects/Tactility/firmware/release/TactilitySDK rm -rf Apps/PocketDungeon/build/cmake-build-esp32s3 PYTHONPATH="" python3 tactility.py Apps/PocketDungeon build esp32s3 --local-sdk # -> Using SDK .../0.8.0-dev-esp32s3/TactilitySDK # -> Building esp32s3 ELF OK # -> Building package OK ``` 5. **Symbol verification (from app skill)** Run the skill's `check_symbols.py` – should show 89 undefined, 0 missing after fix. 6. **Install + screenshot verification** ```bash PYTHONPATH="" python3 tactility.py Apps/PocketDungeon install 192.168.68.112 esp32s3 --local-sdk PYTHONPATH="" python3 tactility.py Apps/PocketDungeon run 192.168.68.112 curl -s http://192.168.68.112/api/screenshot -o /tmp/intro_v3.png # vision analyze: not cramped, airy, no clipping ``` ## QVGA 320x240 cramped UI fix applied Original cramped (intro.png vision): - GOAL card edge-to-edge, text `Loot gold, survive monsters` clipped at bottom - Buttons 85-90% wide touching edges, 4-8px gaps, Best touching bottom - No outer margin Fixed v3 (intro_v3.png vision PASS): - Outer container `pad_all 10`, `pad_row 8` - Cards `PCT 92` width, `SIZE_CONTENT` height, `pad_all 10`, `pad_row 5`, radius 10, bg #1D2030 - ScrollArea `PCT 100`, `flex_grow 1`, scrollable flag, flex col pad_row 8 - TitleBox pad_row 3, title #F8F3E6, subtitle #9AA0B8 - BtnRow `PCT 100`, `SIZE_CONTENT`, flex center, pad_row 8 - Primary btn `PCT 80` 40px accent #365CF5 radius 10 - Secondary exit `PCT 70` 30px bg #252836 radius 8 - Shortened card bodies to fit QVGA: GOAL 1 line, HOW TO PLAY 3 lines, CONTROLS 4 lines - Ends up airy with 12-16px margins, no clipping. Keep text short on QVGA; use `LV_LABEL_LONG_WRAP` + `PCT(100)`. ## Lessons - Always probe board osVersion before build - The `/api/screenshot` endpoint (port 80, not 6666) is invaluable for both crash diagnosis (Error dialog) and layout QA without serial - `max_width` and `scrollbar_mode` specifically are trap APIs – prefer PCT widths for side gutters - TactilitySDK release folder contains both 0.7 and 0.8 subfolders – pick matching one via TACTILITY_SDK_PATH + --local-sdk automatically selects subfolder