# BUG in-app `.pte` 7B/8B (err 5010) — RÉSOLU : mauvaise version de backend QNN chargée par l'app **Date** : 17/06/2026 · **Sévérité** : bloquant in-app pour les `.pte` denses multi-context (≥7B, `num_sharding=2`) **Statut** : **cause isolée** — ce n'est NI le `.pte`, NI le wrapper `libkazeia_pte.so`. C'est l'**intégration app** (résolution de lib QNN). > ⚠️ **Rétracte** `BUG_pte_multicontext_offset_overflow.md` (théorie « overflow int32 » du `.pte`) : **réfutée** par le test CLI ci-dessous. Le `.pte` 8B (2ᵉ context group à 3,24 G > 2 GiB) **charge et génère** sans problème avec le bon runtime. Pas d'overflow. --- ## 1. TL;DR L'erreur in-app `Context group 1 does not exist` / `Error 5010` est la **signature d'un backend QNN trop ancien** (≠ QAIRT 2.42) qui ne sait pas désérialiser la structure **multi-context** (sharding=2) des `.pte` ≥7B. Le backend **2.42** (`ship_runtime/`) les charge parfaitement. **L'app charge un autre `libQnnHtp.so`/backend que celui livré** (collision de SONAME, très probablement avec la pile **ORT-QNN du STT**, ou une lib d'une autre version restée sur le chemin du linker). **Fix** : garantir que c'est bien la pile **QNN 2.42** qui est mappée dans le process app au moment du chargement `.pte` (pas la version du STT/Maven). Aucun changement de `.pte` ni de wrapper. --- ## 2. Preuve d'isolation (décisive) Sur le **même device**, avec le **`ship_runtime/` 2.42 livré**, sur le **même `.pte` Qwen3-8B** (le cas « échec » de la théorie overflow) : | Test sur Qwen3-8B (5,5 G, 2ᵉ context group à 3,24 G > 2 GiB) | Résultat | |---|---| | Runner CLI `qnn_llama_runner` + `ship_runtime` 2.42 | ✅ **313 tokens, 9,65 tok/s**, FR cohérent, EOS propre | | Wrapper `libkazeia_pte.so` (notre JNI) + `ship_runtime` 2.42 | ✅ **41 tokens, 10,3 tok/s**, cohérent | Dans **les deux** cas, le log montre `QnnContextCustomProtocol expected magic 0x5678abcd but get 0x2000000` **ET génère quand même** → **ce message est un INFO bénin présent dans les chargements qui marchent**, pas la cause de l'échec. L'app, elle, enchaîne sur `Context group 1 does not exist / err 5010` : c'est un **second symptôme, propre à l'app**, qui ne sort PAS avec le backend 2.42. Conclusion logique : si c'était un overflow d'offset dans le `.pte` ou dans notre backend, le CLI **et** le wrapper échoueraient aussi. Ils réussissent. **Donc l'app exécute un backend différent.** --- ## 3. Cause racine — collision de version `libQnnHtp` / backend `libkazeia_pte.so` ne `NEEDED` que `libqnn_executorch_backend.so` (le reste statique). Mais ce backend charge à son tour `libQnnHtp.so` / `libQnnSystem.so` **par SONAME**. Si l'APK contient **plusieurs versions** de ces libs — typiquement : - la pile **ORT-QNN du STT** (qui embarque sa propre `libQnnHtp.so`, possiblement une autre version QAIRT), - d'anciennes libs LLM (ère 2.32/2.37) restées dans `jniLibs`, - une AAR QNN Maven, …le linker Android n'en mappe **qu'une seule** par SONAME. Si la version gagnante n'est **pas 2.42**, le backend ExecuTorch reçoit un `libQnnHtp` incompatible → `Context group N does not exist` / `err 5010` sur les `.pte` multi-context. **Pourquoi 4B marche et 7B/8B non** : un backend trop ancien gère encore le layout de contexte simple du 4B, mais **pas** la structure multi-context (2 groups) des modèles plus gros. La forensique avait raison de voir « 2 context groups » sur les 7B/8B — mais la cause n'est pas un overflow dans le `.pte`, c'est le **backend de l'app qui ne sait pas les parser**. Le 2.42 les parse (prouvé §2). --- ## 4. Diagnostic à faire côté dev (confirme la cause en 2 min) **Quelle version de `libQnnHtp` est RÉELLEMENT mappée dans le process app ?** ```bash PID=$(adb shell pidof com.kazeia) adb shell run-as com.kazeia cat /proc/$PID/maps | grep -iE 'libQnnHtp|libqnn_executorch_backend|libQnnSystem' | awk '{print $NF}' | sort -u # puis pour chaque .so mappé : adb shell run-as com.kazeia strings /libQnnHtp.so | grep -m1 AISW_VERSION # doit être 2.42.0 ``` Si la version mappée ≠ **2.42.0**, la cause est confirmée. **Vérifier les doublons de QNN dans l'APK :** ```bash unzip -l app-release.apk | grep -iE 'libQnnHtp|libQnnSystem|libqnn' # ne doit PAS y avoir 2 origines/versions ``` **SHA256 attendus (libs 2.42 de `ship_runtime/`)** — ceux livrés dans `jniLibs/arm64-v8a/` DOIVENT matcher : ``` 95d01368b556f0c6… libqnn_executorch_backend.so 10eb1923b34ac9a7… libQnnHtp.so a69cfc4350c16b22… libQnnSystem.so a08fb34747345125… libQnnHtpV79Stub.so 7ee72b438c97c13c… libQnnHtpV79Skel.so 2daafb376fe6904a… libQnnHtpPrepare.so a3bc48674377a042… libQnnHtpNetRunExtensions.so ``` --- ## 5. Fix 1. **Une seule version de QNN dans l'app** = **2.42** (celle de `ship_runtime/`), pour le STT **et** le LLM `.pte`. Concrètement : - Retirer de `jniLibs` toute `libQnnHtp*.so`/`libQnnSystem.so` qui n'est pas du build 2.42 (anciennes libs LLM, AAR Maven d'une autre version). - Si le STT (ORT-QNN) impose une version QNN différente, **aligner les deux sur 2.42** (le STT marche sur 2.42 ; ORT-QNN EP est tolérant à la version de `libQnnHtp` tant qu'elle ≥ celle de compilation). À défaut, isoler (process séparé) — mais l'alignement sur 2.42 est le plus simple. 2. Re-vérifier le `/proc/pid/maps` : `libQnnHtp.so` mappé = 2.42.0. 3. Aucun ré-export de `.pte`, aucun rebuild de `libkazeia_pte.so` nécessaires. --- ## 6. Reproduction de la PREUVE (artefact sain) ```bash # device, dossier avec le .pte 8B + tokenizer + ship_runtime/ 2.42 + prompt_ids.bin (uint64 LE) ADSP_LIBRARY_PATH=. LD_LIBRARY_PATH=. ./qnn_llama_runner \ -model_path qwen3_8b.pte -tokenizer_path tokenizer.json \ -tokenized_prompt p8b_ids.bin -decoder_model_version qwen3 -eval_mode 1 -seq_len 512 -temperature 0 # Attendu : génère ~300 tokens à ~9-10 tok/s. PAS d'err 5010. ``` Le `ship_runtime/` contient `qnn_llama_runner` + les 7 libs 2.42 : c'est l'oracle « bon backend ». --- ## 7. Données - `.pte` validés (génèrent avec 2.42) : `qwen3_4b_seq1024/`, `qwen3_8b_seq512/`, `qwen2_5_7b_seq512/`, `kazeia-tablet-backup/llm/hybrid_llama_qnn_guard4b.pte`. - Runtime de référence : `/opt/Kazeia/pte_prep_work/ship_runtime/` (QAIRT 2.42, `libQnnHtp` = AISW_VERSION 2.42.0). - À fournir pour clore : `/proc//maps` du process app pendant un load 8B + liste `unzip -l` des `libQnn*` de l'APK.