Files
tactility_apps/.claude/skills/tactility-app-development/references/sdk-mismatch-missing-symbol.md
T
Adolfo Reyna e68909d64d
Main / Build (BookPlayer) (push) Has been cancelled
Main / Build (Brainfuck) (push) Has been cancelled
Main / Build (Breakout) (push) Has been cancelled
Main / Build (Calculator) (push) Has been cancelled
Main / Build (Diceware) (push) Has been cancelled
Main / Build (EpubReader) (push) Has been cancelled
Main / Build (GPIO) (push) Has been cancelled
Main / Build (GraphicsDemo) (push) Has been cancelled
Main / Build (HelloWorld) (push) Has been cancelled
Main / Build (M5UnitTest) (push) Has been cancelled
Main / Build (Magic8Ball) (push) Has been cancelled
Main / Build (MediaKeys) (push) Has been cancelled
Main / Build (MystifyDemo) (push) Has been cancelled
Main / Build (SerialConsole) (push) Has been cancelled
Main / Build (Snake) (push) Has been cancelled
Main / Build (TamaTac) (push) Has been cancelled
Main / Build (TodoList) (push) Has been cancelled
Main / Build (TwoEleven) (push) Has been cancelled
Main / Bundle (push) Has been cancelled
chore: move app skill in-repo + AGENTS.md
- Migrates tactility-app-development from ~/.hermes/skills/ into
  .claude/skills/ for repo co-location
- Adds AGENTS.md with local workstation context, hardware table,
  board-direct build/env wrapper (PYTHONPATH fix), ELF missing-symbol
  triage, app patterns (immersive, QVGA rail, tutorial 2-row,
  GameKit bubbling, screenshot rate-limit), and skill index

Refs: personal Gitea mirror
2026-07-17 09:51:20 -04:00

4.4 KiB
Raw Blame History

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:
      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

    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

    [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:

    // 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:

    // 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

    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

    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