Diagnóstico de fallos
1. Cómo usar este catálogo
Es un índice de síntomas. Se entra por el mensaje literal que se tiene delante, no por el concepto, porque cuando algo falla lo único que se tiene es una cadena de texto y ninguna pista de a qué capa pertenece. Cada entrada tiene la misma forma —síntoma literal → qué significa → causa raíz → qué comprobar → cómo se arregla— y una convención de honestidad: (reproducido) marca lo provocado en la máquina de referencia, con la cadena copiada de la salida real; (fuente) marca lo copiado del código que lo emite —AOSP, jadx o apktool— con el fichero identificado pero sin reproducir aquí; y ⚠️ marca lo que no está verificado, diciendo por qué.
Dos avisos generales. Los mensajes de error mienten sobre la causa con frecuencia: el caso de
manual está en §4.2, donde un zipalign ejecutado un paso tarde produce Signature stripped?, que
suena a ataque y es un error de orden. Y el error real casi nunca está en la salida de la orden que
falló: en instalación está en logcat; en apktool, en el log de aapt2 y no en la excepción; en
jadx, en el .java generado y no en la consola.
2. Instalación: los códigos INSTALL_*
2.1 De dónde salen y cómo se leen
Están enumerados en frameworks/base/core/java/android/content/pm/PackageManager.java de AOSP.
Todos los valores son negativos, todos los símbolos están marcados @hide —no son API pública—
y adb install los devuelve como texto, sin el número. Dos familias que llevan a sitios distintos:
INSTALL_PARSE_FAILED_* (−100 a −109, más −124 y −125) significa que el paquete no se pudo
leer —el fallo está en el fichero y lo produce el analizador—; INSTALL_FAILED_* (−1 a −29 y
−110 en adelante) significa que el paquete se leyó bien y el sistema lo rechaza por su relación
con lo instalado, con el dispositivo o con la política. Y una regla operativa: el motivo concreto
está en logcat, no en la salida de adb install — el instalador devuelve un código seco, y el
mensaje que dice qué entrada, qué certificado o qué split falla lo escribe PackageManager en el
log del sistema.
⚠️ Ninguno de estos códigos se ha reproducido: no hay dispositivo Android ni emulador conectado al entorno de referencia y
adbno está en elPATH. Los valores, las descripciones y los mensajes internos proceden del código de AOSP en la ramamain, leído directamente (?format=TEXT, decodificado) el 12 de agosto de 2026. Nada de esta sección es una salida observada.
2.2 Fallos de análisis del paquete
| Código | Valor | Qué significa | Dónde se lanza y con qué condición |
|---|---|---|---|
..._NOT_APK |
−100 | La ruta no es un fichero o no acaba en .apk |
ApkLiteParseUtils: directorio sin paquetes (No packages found in split), o ApkAssets.loadFromFd lanza IOException |
..._BAD_MANIFEST |
−101 | No se pudo recuperar el manifiesto | ApkLiteParseUtils: splits que discrepan del primero (Inconsistent package…, Inconsistent version…), nombre de split repetido, o Missing base APK in <dir> |
..._UNEXPECTED_EXCEPTION |
−102 | Excepción inesperada | parseApkLiteInner(): catch general de XmlPullParserException | IOException | RuntimeException. Cajón de sastre: no dice nada por sí mismo, el motivo está en logcat |
..._NO_CERTIFICATES |
−103 | Sin certificados utilizables | §2.3 |
..._INCONSISTENT_CERTIFICATES |
−104 | Certificados incoherentes | §2.3 |
..._CERTIFICATE_ENCODING · ..._BAD_SHARED_USER_ID · ..._MANIFEST_EMPTY |
−105 · −107 · −109 | CertificateEncodingException en algún fichero · sharedUserId inválido · ni <application> ni <instrumentation> |
ApkSignatureVerifier · ApkLiteParseUtils · ParsingPackageUtils |
..._BAD_PACKAGE_NAME |
−106 | Nombre de paquete inválido o ausente en el manifiesto | §2.3 |
..._MANIFEST_MALFORMED |
−108 | Problema estructural en el manifiesto | §2.3 |
..._RESOURCES_ARSC_COMPRESSED |
−124 | resources.arsc comprimido o desalineado |
§2.3 |
2.3 Los cinco que hay que conocer al detalle
INSTALL_PARSE_FAILED_NO_CERTIFICATES. El paquete no tiene firma utilizable, o no la que el
rango de API exige. Lo produce ApkSignatureVerifier.java en varios sitios con mensajes distintos:
cuando el esquema mínimo requerido es más nuevo que cualquiera de los presentes —"No signature found in package of version … or newer for package …"—, cuando se captura
SignatureNotFoundException y no se puede caer a un esquema anterior —"No APK Signature Scheme v4/v3/v2 signature in package …"— y, en el camino de v1, "Package … has no certificates at entry AndroidManifest.xml". En la práctica, tres orígenes: se olvidó firmar —apktool, APKEditor y
bundletool build-apks sin --ks producen APK sin firma por diseño—, se firmó solo con v1
teniendo un targetSdk que exige v2 (§3.3), o se pasó zipalign después de firmar (§4.2).
Comprobar: apksigner verify --verbose --min-sdk-version <el minSdk real> app.apk, y el
inventario físico de META-INF/. Arreglo: firmar en el orden correcto —alinear y después
apksigner sign con v2 y v3 (Pipeline de modificación, §7.4).
INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES. Dentro del paquete —o del conjunto de splits—
no todo está firmado por lo mismo. Dos sitios: ApkSignatureVerifier.java en la verificación
completa de v1, cuando una entrada del ZIP tiene firmas distintas de las del manifiesto
("Package … has mismatched certificates at entry …"); y ParsingPackageUtils.getSigningDetails()
/ FrameworkParsingPackageUtils, cuando !Signature.areExactMatch(...) entre un split y el base
("<baseCodePath> has mismatched certificates"). El segundo es el frecuente, y aparece al
instalar splits refirmados por separado o al mezclar splits de dos descargas. Comprobar: un bucle
de apksigner verify --print-certs sobre todos los splits tiene que devolver un solo
certificate SHA-256 digest (Pipeline de análisis, §5.4). Arreglo:
refirmar todos con la misma clave, cada uno alineado antes.
INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME. Lo produce
FrameworkParsingPackageUtils.validateName(), cuyas reglas están implementadas ahí literalmente y
no en ninguna especificación. Recorre carácter a carácter con dos banderas, front y hasSep:
[a-zA-Z] siempre vale y pone front = false; [0-9] y _ valen solo si front == false, o
sea que un segmento no puede empezar por dígito ni por subrayado; . pone hasSep = true y
front = true; y cualquier otro carácter da "bad character '<c>'". Con requireFilename añade
"Invalid filename" y "the length of the name is greater than 223"; y al final, con
requireSeparator y sin ningún punto, "must have at least one '.' separator". El paquete se valida
con requireSeparator=true, requireFilename=true; los nombres de split con false, false; los
tipos con false, true. Aparece casi siempre tras un --rename-manifest-package con un guion,
un segmento que empieza por dígito (com.ejemplo.2app) o ningún punto.
INSTALL_PARSE_FAILED_MANIFEST_MALFORMED. Varios sitios de ApkLiteParseUtils.java, con
mensajes muy informativos si se llegan a ver en logcat: "No start tag found",
"No <manifest> tag", "Invalid manifest split types: ", un <uses-split> sin android:name, o un
<uses-sdk-library> / <uses-static-library> mal formado o duplicado. Al fusionar splits la causa
habitual es otra —quedaron atributos de split en el manifiesto del resultado
(Fusión de splits, §5)—, y sobre un APK fusionado el
aapt2 dump xmltree … | grep -E "split=|splitTypes|isSplitRequired|isFeatureSplit|configForSplit"
no debe devolver nada. Si el manifiesto ni siquiera se puede leer, el error está un nivel más abajo
y aapt2 lo dice con precisión: §8.3.
INSTALL_PARSE_FAILED_RESOURCES_ARSC_COMPRESSED — con la trampa reproducida. Significa que
el resources.arsc de alguno de los APK va comprimido o no está alineado a 4 bytes, así que el
sistema no lo puede mapear con mmap. Lo produce ParsingPackageUtils.parseBaseApk(): tras un
análisis correcto del manifiesto comprueba assets.containsAllocatedTable() —la tabla tuvo que
reservarse en RAM en vez de mapearse— y emite un error diferido con el identificador de cambio
de comportamiento RESOURCES_ARSC_COMPRESSED = 132742131, anotado
@EnabledAfter(targetSdkVersion = Q): solo se activa para targetSdk 30 y superior; con 29 o
menos, el mismo APK instala. El texto en AOSP es "Targeting R+ (version 30 and above) requires the resources.arsc of installed APKs to be stored uncompressed and aligned on a 4-byte boundary".
Y aquí está la trampa: las herramientas locales no lo detectan. Sobre un APK construido a
propósito con resources.arsc comprimido, aapt2 dump badging responde con normalidad
(package: name='org.fossify.math' versionCode='10' …) y zipalign -c -v 4 lo marca
3322768 resources.arsc (OK - compressed) saliendo con 0. La comprobación hay que hacerla a mano
—zipfile.ZipFile(apk).getinfo('resources.arsc').compress_type == 0— y el arreglo es reempaquetar
forzando stored en esa entrada.
2.4 Fallos de instalación
| Código | Valor | Qué significa |
|---|---|---|
INSTALL_FAILED_INVALID_APK |
−2 | El archivo del paquete es inválido |
INSTALL_FAILED_INSUFFICIENT_STORAGE |
−4 | No hay espacio suficiente en el dispositivo |
INSTALL_FAILED_UPDATE_INCOMPATIBLE |
−7 | Ya hay un paquete con ese nombre y firma distinta, y sus datos no se borraron |
INSTALL_FAILED_DEXOPT |
−11 | Falló la optimización o la validación de los DEX |
INSTALL_FAILED_OLDER_SDK |
−12 | El minSdkVersion es mayor que la versión del dispositivo |
INSTALL_FAILED_CPU_ABI_INCOMPATIBLE |
−16 | Trae código nativo y ninguna ABI es compatible |
INSTALL_FAILED_VERSION_DOWNGRADE |
−25 | El versionCode es menor que el instalado |
INSTALL_FAILED_MISSING_SPLIT |
−28 | Requiere al menos un split y no se aportó |
INSTALL_FAILED_INTERNAL_ERROR |
−110 | Fallo del sistema |
INSTALL_FAILED_NO_MATCHING_ABIS |
−113 | El código nativo no coincide con ninguna ABI del sistema |
INSTALL_FAILED_ABORTED |
−115 | Sin Javadoc en AOSP: solo /** {@hide} */ |
⚠️ INSTALL_FAILED_MULTI_ARCH_NOT_SUPPORTED no existe. Circula en foros, pero no aparece en
PackageManager.java de la rama main. La constante real más cercana es
INSTALL_FAILED_MULTI_ARCH_NOT_MATCH_ALL_NATIVE_ABIS = -131, para aplicaciones con
android:multiArch="true" cuyo código nativo no cubre todas las ABIs del sistema.
INSTALL_FAILED_UPDATE_INCOMPATIBLE. InstallPackageHelper.preparePackage(), en el camino de
reemplazo, cuando las credenciales de firma nuevas no tienen CertCapabilities.INSTALLED_DATA
respecto a las instaladas y no es un rollback válido a un ancestro del linaje:
"New package has a different signature: " + pkgName. Hay otras dos rutas al mismo código —fallo de
checkUpgradeKeySetLocked, y un cambio de SDK en una biblioteca sin subir su versionMajor— y una
cuarta que AOSP reconoce como reutilización indebida: en scanInstallPackages() se devuelve el mismo
código cuando la actualización cambia PROPERTY_NO_APP_DATA_STORAGE, con un TODO en el fuente
admitiendo que no corresponde. Es decir: no siempre es de firma. En la práctica aparece siempre
que se instala un APK refirmado encima del original, lo cual es inevitable
(Pipeline de modificación, §7.3), y el único arreglo es
adb uninstall con pérdida de los datos.
INSTALL_FAILED_VERSION_DOWNGRADE. La comprobación real es
PackageManagerServiceUtils.checkDowngrade(), más fina de lo que sugiere el nombre: falla si el
versionCode nuevo es menor, o si son iguales y el baseRevisionCode nuevo es menor, o si
el splitRevisionCode de cualquier split coincidente es menor — salvo que isDowngradePermitted()
lo autorice, lo que ocurre con adb install -d sobre una compilación depurable. Ojo con haber
tocado el versionCode al reempaquetar sin querer: apktool lo repuebla desde apktool.yml.
INSTALL_FAILED_MISSING_SPLIT. PackageInstallerSession.validateApkInstallLocked(), en dos
sitios y los dos con el mensaje "Missing split for " + mPackageName: en instalación completa,
cuando baseApk.isSplitRequired() y stagedSplits.size() <= 1 o
!stagedSplitTypes.containsAll(requiredSplitTypes); y heredando, cuando se han quitado todos los
splits o los tipos aportados no cubren los requeridos. Hay que mirar los dos mecanismos que
conviven —el booleano isSplitRequired y el par requiredSplitTypes/splitTypes—, porque el corpus
tiene aplicaciones con cada uno (Fusión de splits, §5.2). Arreglo:
adb install-multiple con el conjunto completo, o fusionar y sanear el manifiesto.
INSTALL_FAILED_NO_MATCHING_ABIS y INSTALL_FAILED_CPU_ABI_INCOMPATIBLE. Casi siempre al
fusionar splits cogiendo de menos. Es el único de los tres ejes que produce un fallo duro
—densidad e idioma degradan en silencio (Fusión de splits, §3.1)—, y se
comprueba comparando las ABIs bajo lib/ con adb shell getprop ro.product.cpu.abilist.
3. Firma
3.1 DOES NOT VERIFY — el prefijo común
apksigner verify responde siempre con esa línea, sale con código 1, y el motivo va en las líneas
ERROR: siguientes. Los cinco que se ven de verdad:
Línea ERROR: |
Causa |
|---|---|
Missing META-INF/MANIFEST.MF |
No hay firma ninguna, o se destruyó el APK Signing Block y no había v1 · §3.2 |
JAR signature META-INF/X.SF indicates the APK is signed using APK Signature Scheme v2 but no such signature was found. Signature stripped? |
Había v1 y v2/v3, y el bloque desapareció · §4.2 |
APK integrity check failed. CHUNKED_SHA256 digest mismatch. |
El contenido cambió después de firmar · §3.2 |
Target SDK version 36 requires a minimum of signature scheme v2; the APK is not signed with this or a later signature scheme |
Se firmó solo con v1 · §3.3 |
Verified using vN scheme: false sin DOES NOT VERIFY |
No es un error: es la trampa del rango de SDK · §3.4 |
3.2 Bloque desaparecido frente a contenido modificado (reproducido)
Es la distinción que más tiempo ahorra, y las dos familias se confunden constantemente.
ERROR: Missing META-INF/MANIFEST.MF significa que el verificador no encontró ningún bloque de
firma y cayó al camino de v1, donde lo primero que busca es MANIFEST.MF. Dos causas: el APK
nunca se firmó —apktool, APKEditor y bundletool build-apks sin --ks producen APK sin firma
por diseño; reproducido sobre un APK del corpus sin META-INF/ y sobre el universal.apk de
bundletool --mode=universal— o se ejecutó zipalign después de firmar un APK que solo tenía
v2/v3 (§4.2). Si unzip -l app.apk | grep META-INF no devuelve nada y el APK mide menos que
antes, es el segundo caso: hay que firmar el de antes de alinear.
CHUNKED_SHA256 digest mismatch significa lo contrario: el bloque sigue ahí y es legible, y lo
que no cuadra es el digest. Cambiando un solo byte dentro de resources.arsc de un APK ya
firmado, sin mover ningún offset —el fichero mide exactamente lo mismo antes y después—:
DOES NOT VERIFY
ERROR: APK Signature Scheme v3 signer #1: APK integrity check failed. CHUNKED_SHA256 digest mismatch. Expected: <655a9adc…cafe8d6c>, actual: <bf95b77b…39f57b21>
La regla:
digest mismatches contenido modificado —«alguien tocó el fichero»—;Signature stripped?yMissing META-INF/MANIFEST.MFson bloque desaparecido —casi siempre, «se ejecutó una herramienta en el orden equivocado»—. El arreglo, en los dos casos, es volver a firmar (§3.5).
3.3 Target SDK version 36 requires a minimum of signature scheme v2 (reproducido)
Firmando una copia del corpus con --v1-signing-enabled true y las demás a false:
DOES NOT VERIFY
ERROR: Target SDK version 36 requires a minimum of signature scheme v2; the APK is not signed with this or a later signature scheme
WARNING: META-INF/com/android/build/gradle/app-metadata.properties not protected by signature. …
WARNING: META-INF/version-control-info.textproto not protected by signature. …
Firmar solo con v1 hoy es no firmar: la firma es criptográficamente correcta y el APK no se
instala, porque Android exige un esquema mínimo según el targetSdkVersion. Cuatro de las trece
herramientas de Comparativa y selección firman
solo con v1, y sus APK parecen correctos hasta el último paso. Los WARNING son el otro dato:
la firma JAR no cubre las entradas de META-INF/, así que
cualquiera puede modificarlas sin invalidarla — la debilidad que motivó v2. Arreglo:
--v2-signing-enabled true --v3-signing-enabled true; v1 solo si minSdkVersion < 24.
3.4 Verified using v1 scheme: false con el MANIFEST.MF dentro (reproducido)
No hay fallo. apksigner verify no responde «¿está presente este esquema?» sino «¿se usó este
esquema para verificar en el rango de API que me has dado?». El mismo APK firmado con v1+v2+v3,
con dos rangos distintos, da Verified using v1 scheme (JAR signing): false con
--min-sdk-version 24 y true con 21 — y META-INF/PROC.SF, META-INF/PROC.RSA y
META-INF/MANIFEST.MF están dentro en los dos casos. Para saber qué esquemas hay, se mira el
ZIP y el APK Signing Block; para saber si instalará, se ejecuta verify con el
minSdkVersion real de la aplicación.
3.5 Fallos al firmar (reproducidos)
| Síntoma | Causa | Arreglo |
|---|---|---|
Failed to load signer "signer #1" + java.io.IOException: keystore password was incorrect |
Contraseña del keystore incorrecta | Revisar --ks-pass; preferir env: o file: sobre pass: |
Failed to load signer "signer #1": x.p12 entry "ALIAS" does not contain a key |
El alias no existe | keytool -list -v -keystore x.p12 |
com.android.apksig.apk.ApkFormatException: Malformed APK: not a ZIP archive |
No es un ZIP |
§8.1 |
com.android.apksig.apk.ApkFormatException: Missing AndroidManifest.xml |
Es un ZIP pero no un APK |
Se cogió el contenedor en vez del APK de dentro |
Y la imposibilidad de fondo: la firma original nunca se puede conservar tras modificar el contenido. No es una limitación de las herramientas, es la propiedad que hace útil a la firma (Pipeline de modificación, §7.3).
4. Alineación
4.1 (BAD - n) de zipalign -c (reproducido)
Sobre split_config.arm64_v8a.apk del SAI de Netflix del corpus:
4096 lib/arm64-v8a/libavif_android.so (BAD - 4096)
851968 lib/arm64-v8a/libbugsnag-ndk.so (OK)
2039808 lib/arm64-v8a/libbugsnag-plugin-android-anr.so (BAD - 8192)
7974912 lib/arm64-v8a/libtensorflowlite_jni_gms_client.so (BAD - 12288)
Verification FAILED
El n no es un código de error: es el resto de dividir el offset de los datos entre la
alineación exigida. libavif_android.so empieza en el byte 4.096, y 4096 mod 16384 = 4096: o
sea, cuántos bytes sobran. Causa raíz: el APK está alineado a 4 KiB y se le exige 16 KiB, y el
mismo fichero con zipalign -c 4 sale con 0 —las mismas entradas, dos veredictos opuestos,
porque son dos preguntas distintas—. Esos seis splits de Netflix son el único incumplimiento de
16 KB en los 717 APK del corpus. Arreglo: zipalign -P 16 -f 4 entrada.apk salida.apk,
antes de firmar.
Los tres veredictos por entrada: (OK) es stored y alineada; (OK - compressed) es comprimida y
la alineación no le aplica; (BAD - n) es stored desalineada por n bytes.
4.2 La trampa mayor: zipalign después de firmar (reproducido)
El fallo de manual del ecosistema, y el que produce el diagnóstico más engañoso.
$BT/apksigner verify --verbose firmado.apk | head -4 # v1 + v2 + v3, todo correcto
$BT/zipalign -p -f 4 firmado.apk roto.apk; echo "zipalign exit=$?"
$BT/apksigner verify --verbose roto.apk; echo "verify exit=$?"
zipalign exit=0
DOES NOT VERIFY
ERROR: JAR signer PROC.RSA: JAR signature META-INF/PROC.SF indicates the APK is signed using APK Signature Scheme v2 but no such signature was found. Signature stripped?
ERROR: JAR signer PROC.RSA: JAR signature META-INF/PROC.SF indicates the APK is signed using APK Signature Scheme v3 but no such signature was found. Signature stripped?
verify exit=1
zipalign no invalida la firma: la borra. Reescribe el ZIP entrada por entrada a un fichero
nuevo, con Central Directory y EOCD nuevos, y el hueco donde vivía el APK Signing Block no
se reproduce. El .SF de v1 sí sobrevive —es una entrada normal del ZIP— y sigue declarando
X-Android-APK-Signed: 2, 3; el verificador ve esa declaración, no encuentra los bloques, y acusa
de un stripping que no hubo. Y si el APK no tenía v1, el mensaje es aún más desconcertante —mismo
experimento firmando solo con v2+v3: DOES NOT VERIFY / ERROR: Missing META-INF/MANIFEST.MF—: un
fichero que nunca tuvo MANIFEST.MF, acusado de que le falta.
La señal delatora: zipalign devolvió 0. Para él la operación fue un éxito. Y el APK
resultante mide algunos kilobytes menos que el firmado: la diferencia es el bloque desaparecido más
el relleno recalculado. Arreglo: recuperar el APK de antes de firmar, alinearlo y firmar
después.
| Orden | Resultado |
|---|---|
| construir → alinear → firmar | Correcto |
| construir → firmar → alinear | Firma destruida |
| construir → firmar → tocar un fichero | digest mismatch (§3.2) |
alinear → firmar → zipalign -c |
Correcto: -c solo lee |
4.3 zipalign -c pasa y el APK sigue siendo incompatible con 16 KB
zipalign -c responde a «¿están alineadas las entradas que debían estarlo?», no a «¿cumple este
APK la regla de 16 KB?». Un APK con extractNativeLibs="true" comprime sus .so, no tiene
ninguna entrada a la que la regla aplique, y pasa siempre. Y hay un segundo requisito que zipalign
no mira: los segmentos LOAD del propio ELF tienen que estar alineados a 2**14. Los dos
controles son necesarios y ninguno basta (Alineación,
§3.1, y Código nativo y ELF).
5. apktool
⚠️ Nada de esta sección está reproducido: apktool no está instalado y estas reglas prohíben instalarlo. Las cadenas literales proceden del código fuente del proyecto, leído directamente en el commit
79b6338del 10 de agosto de 2026 —ramamain, que es la 3.x— y en los tagsv2.7.0yv2.9.3para las variantes antiguas.
5.1 El aviso de versión, que es la mitad del problema
Las cadenas cambiaron entre 2.x y 3.x, y las que circulan por los foros son las antiguas: si se busca un mensaje y no aparece, casi siempre es esto.
| 2.x | 3.x (main) |
|---|---|
Paquete brut.androlib.err · clase CantFindFrameworkResException |
Paquete brut.androlib.exceptions · clase FrameworkNotFoundException |
Can't find framework resources for package of id: 1 |
Could not find framework resources for package ID 1. + salto de línea + You must install proper framework files, see project website for more info. |
Could not decode arsc file (sin punto) |
Could not decode arsc file. (con punto) |
Invalid config flags detected. Dropping resources: |
Invalid resource config detected. Dropping resources: %s %s |
⚠️ El texto de ayuda de --keep-broken-res en el Main.java de 3.x sigue citando la redacción 2.x
del mensaje al que remite: está desactualizado en el propio proyecto.
5.2 Las excepciones de brut.androlib (3.x)
| Clase | Mensaje literal |
|---|---|
AndrolibException |
Clase base, sin mensaje fijo. Extiende brut.common.BrutException |
FrameworkNotFoundException |
Could not find framework resources for package ID <id>. + You must install proper framework files, see project website for more info. |
InFileNotFoundException · OutDirExistsException · RawXmlEncounteredException · NinePatchNotFoundException |
Input file (<ruta>) was not found or was not readable. · Destination directory (<ruta>) already exists. Use -f option if you want to overwrite it. · Could not decode XML. · Could not find nine patch chunk. |
InFileNotFoundException, OutDirExistsException y FrameworkNotFoundException se imprimen sin
traza de pila y con salida 1; el resto, con traza. Y falta una más, UndefinedResObjectException,
cuyo mensaje es estructurado —entry: pkgId=0x%02x, typeId=0x%02x, entryId=0x%04x, config=%s,
overlayable: pkgId=0x%02x, name=%s— y dice exactamente qué identificador no resolvió.
Could not find framework resources for package ID 1. apktool no tiene el APK de framework
para resolver los identificadores del espacio 0x01....... Trae empotrado el framework estándar, así
que con aplicaciones normales de Play no pasa: pasa con las de sistema y de fabricante —Samsung,
MIUI, HTC—. Arreglo: apktool if framework-res.apk, o apktool if -t miui framework-miui-res.apk y
luego apktool d -t miui app.apk.
Could not decode arsc file. El lector de resources.arsc de apktool se atascó, y las issues
cerradas identifican el patrón: el tamaño declarado de un chunk no corresponde al contenido.
iBotPeaches en la #3036: «what appears to be happening is the reported size of a chunk is wrong …
the chunks we are reading are exceeding the size that was reported of that chunk»; en la #2989:
«The header chunk is lying about its reported size.» Segunda familia: las tablas sparse
(#3199, #3298), donde el criterio correcto no es el orden de los chunks sino el propio flag de
sparse, con el umbral de AOSP de al menos 1.000 recursos.
⚠️ --force-manual-size no existe y nunca ha existido en apktool: se buscó en los 2.376 commits
de todas las ramas del repositorio, desde 2010, y en la documentación oficial, con cero apariciones.
El control de sparse es la clave sparseResources de apktool.yml, no un flag; si una guía lo
menciona, viene de un fork.
Qué comprobar: si aapt2 dump resources sí lee el fichero, el problema es de apktool y no de
la tabla. Arreglos por coste: apktool d -r, --keep-broken-res, o APKEditor, que usa otro
lector.
Invalid resource config detected. Dropping resources: … es un aviso, no un error: apktool
ha encontrado una configuración que no entiende y está descartando esos recursos; la ejecución
continúa y el resultado está incompleto. --keep-broken-res los conserva, y hay que arreglarlos a
mano antes de reconstruir.
5.3 Fallos de reconstrucción por aapt2
Aquí está el detalle que hace perder más tiempo: apktool no aporta ningún mensaje propio. El
envoltorio de aapt2 captura la BrutException y la reenvuelve en un AndrolibException(ex) sin
mensaje, solo con la causa, así que lo que se ve es lo que produce brut.util.OS.exec:
Execution failed (exit code = 1): [.../aapt2, link, -o, ..., --manifest, ...]. Los errores reales
de aapt2 —los error: resource … is private, los Multiple resources— llegan por un camino
distinto: un reenviador de flujos que los registra en el log a nivel warn. Por eso aparecen en
el log y nunca en el texto de la excepción, y por eso buscar «Multiple resources» en el código
de apktool no devuelve nada. Hay que subir el nivel de log y leer las líneas de aapt2.
Error de aapt2 |
Causa | Arreglo |
|---|---|---|
resource … is private |
El APK original referencia un recurso del framework marcado como privado. Es legal en un binario construido y aapt2 lo rechaza al enlazar, porque su trabajo es impedirlo |
apktool d -r, o APKEditor |
Multiple resources / símbolos duplicados |
Identificadores que apktool no supo resolver y sustituyó por @null. Issue #2836: «This works for the first resource, but as you see becomes duplicate symbols» |
Actualizar apktool, o APKEditor |
Dos datos más: apktool siempre pasa --legacy a aapt2 —comentario del fuente: «Treats error that
used to be valid in aapt1 as warnings in aapt2»— y aapt1 ya no existe, Main.java responde
Legacy aapt is no longer supported. desde 2025.
5.4 Lo que apktool no hace, y hay que saber
- No firma. La FAQ oficial: «Apktool builds unsigned APKs. This means some directories and files like META-INF are missing.»
- No alinea. Verificado por inspección del código fuente de la rama
main: no hay ninguna referencia azipalign, a alineación de página ni a 16.384. Registra qué entradas vanstoredendoNotCompressy las escribe sin comprimir, pero nunca las alinea:zipalignes estrictamente externo. --copy-originalsolo sirve para v1 (FAQ), y--match-originalimpide reconstruir: la ayuda dice literalmenteKeep files closest to original as possible (prevents rebuild).- Hay
APKque no soporta: los construidos con herramientas modificadas para OEM concretos «are not built with regular AOSP tools and are not compatible with Apktool».
6. jadx
⚠️ Nada de esta sección está reproducido: jadx no está instalado y estas reglas prohíben instalarlo. Las cadenas literales proceden del código fuente del proyecto, leído directamente en el commit
e738a26del 5 de agosto de 2026, con fichero y línea identificados.
6.1 Corrección previa: dos cadenas que circulan y no existen
| Cadena que circula | Realidad |
|---|---|
// decompilation failed |
No existe en jadx. No aparece en ninguna parte del árbol. Lo más parecido es "Class decompilation failed", mensaje de una JadxRuntimeException del modo --single-class, no un comentario del código generado |
// JADX WARNING: inconsistent code |
La forma real es /* JADX WARN: <mensaje> */. Y no se puede buscar en el fuente: se compone en ejecución como "JADX " + nivel.name() + ": " en JadxCommentsAttr, así que grepear el repositorio no devuelve nada y lleva a concluir que es falsa |
⚠️ La sección 3.5 de Decompiladores a Java cita las dos formas incorrectas. Los modos de fallo que describe son correctos; los literales, no.
6.2 Los marcadores reales, con su fichero
| Literal | Dónde se emite | Qué significa |
|---|---|---|
/* JADX ERROR: <msg> … */ (con dos espacios tras /*) |
codegen/utils/CodeGenUtils.java:48 |
Error duro en ese nodo. Si hay causa, la traza de pila Java completa va incrustada dentro del comentario |
/* JADX WARN: … */, /* JADX INFO: … */, /* JADX DEBUG: … */ |
JadxCommentsAttr + CodeGenUtils.addComments |
Aviso del nivel correspondiente. Por defecto --comments-level es info: WARN e INFO se emiten, DEBUG no |
Code decompiled incorrectly, please refer to instructions dump. + To view partially-correct add '--show-bad-code' argument |
codegen/MethodGen.java:114-127 |
El peligroso. Ver §6.3. La falta de la palabra «code» en el segundo está en el fuente, no es errata de este documento |
throw new UnsupportedOperationException("Method not decompiled: …") |
MethodGen.java:365-373 |
El método no se reconstruyó; se emite un lanzamiento para que el fichero siga siendo parseable |
Method dump skipped, instruction units count: <n> + To view this dump add '--comments-level debug' option |
MethodGen.java:381 y :385 |
El volcado se omitió por tamaño; el umbral es más de 200 unidades de instrucción |
// Can't load method instructions: <msg> / // Can't load method instructions. · // Blocks not ready for simple mode, using fallback |
MethodGen.java:402, :410 · :308 |
No se pudieron decodificar las instrucciones · cayó al modo de respaldo |
Load error · Code generation failed |
RootNode.java:192 · ClassNode.java:409 |
Fallo al cargar la entrada · ver §6.4 |
Mensajes representativos tras JADX WARN:, verbatim del fuente: Multi-variable type inference failed, Type inference incomplete: some casts might be missing, Unreachable blocks removed: ,
Failed to restore switch over string. Please report as a decompilation issue.
6.3 Code decompiled incorrectly — el que hay que tomarse en serio
No es un comentario de una línea: es un bloque de tres.
/*
Code decompiled incorrectly, please refer to instructions dump.
To view partially-correct add '--show-bad-code' argument
*/
Significa que jadx llegó a producir Java y luego detectó que su propia reconstrucción no es coherente con el grafo de partida; por defecto no lo enseña y sustituye el cuerpo por el volcado.
El mecanismo, que aclara la confusión habitual: ClassGen.addMethodCode tiene tres niveles.
Aviso (addWarn) pone la bandera INCONSISTENT_CODE, añade el comentario JADX WARN y suma al
contador — un solo aviso ya basta para que el método caiga al modo de respaldo. Error
(addError) añade el atributo JADX_ERROR y fuerza el respaldo igualmente. El fallo de clase entera
es §6.4. Y --show-bad-code no arregla nada: solo cambia la bandera para que se imprima el Java
parcialmente reconstruido —que puede ser incorrecto— en lugar del volcado. Es la opción correcta
para auditar y la peligrosa para confiar.
Y el dato que corrige un error extendido: jadx no emite smali en el fichero .java. Lo que
pone en el modo de respaldo es su volcado de instrucciones interno, en su propia representación;
el smali de verdad existe solo como superficie de API —JavaClass.getSmali()—, alimenta la
pestaña «Smali» de jadx-gui y nunca aparece en la salida de la CLI.
6.4 Un fichero .java cuyo contenido entero es una traza de pila
La clase entera falló. ClassNode.generateClassCode() captura StackOverflowError | Exception,
registra "Code generation failed" y devuelve como contenido del fichero la traza de pila en
crudo. Un pipeline que cuente .java producidos concluirá que la clase se decompiló.
6.5 Salida vacía, cuelgues y OutOfMemoryError
Causa raíz, con explicación del mantenedor. La issue #2676, cerrada: «errors during instructions
decoding handled per single instruction, but there are several big methods (~100K instruction units)
with errors at almost all instructions, so all these errors are collected to be added into generated
code later (JADX_ERROR attribute). This is very slow and eats a lot of memory.» Es decir: un
DEX con anti-análisis produce un error por instrucción, y acumularlos mata el proceso. La #2744
es análoga para código muy ofuscado. Arreglos: JAVA_OPTS="-Xmx8g", -j 4, excluir paquetes,
jadx-gui con su caché en disco, o -m fallback.
6.6 Los códigos de salida, que sí sirven para automatizar
| Código | Condición |
|---|---|
| 0 | Éxito |
| 1 | JadxArgsValidateException (Incorrect arguments: {}) o cualquier Throwable (Process error:) |
| 2 | No se cargó ninguna clase y se pasó --no-res: Load failed! No classes for decompile! |
| 3 | Decompiló, pero con errores. Imprime el informe y luego finished with errors, count: {} |
El 3 es el que importa: hay salida, y parte de ella son trazas de pila y volcados de
instrucciones. Un 0, en cambio, no garantiza cobertura completa: los avisos no cuentan como
error y ya bastan para que un método caiga al modo de respaldo. El informe previo lo emite
ErrorsCounter.printReport() con los formatos "{} errors occurred in following nodes:" y
"{} warnings in {} nodes".
7. Fusión de splits
| Síntoma | Causa raíz | Qué comprobar |
|---|---|---|
NoClassDefFoundError en ejecución |
Falta un DEX, la renumeración dejó un hueco, o el DEX de un feature module quedó delante de los del base y sombreó una clase |
unzip -l final.apk | grep -oE "classes[0-9]*\.dex" | sort -V — consecutiva y sin huecos |
| Los textos salen en inglés; los iconos, borrosos | La tabla de recursos no se fusionó. Los ficheros de res/ se copiaron y ninguna entrada apunta a ellos |
aapt2 dump badging final.apk | grep -E "^(locales|densities|native-code)". Si locales es solo '--_--', no se fusionó |
Un módulo de funcionalidad no está · dos Package con el mismo id= |
Se descartaron los splits con isFeatureSplit=true o su paquete propio · colisión real de package ID |
aapt2 dump resources final.apk | grep "^Package" debe listar dos paquetes con id distintos. La colisión es un aborto, no un aviso |
INSTALL_FAILED_MISSING_SPLIT sobre el fusionado |
Quedaron atributos de split en el manifiesto | §2.3 y Fusión de splits, §5 |
Instala y muere en System.loadLibrary |
extractNativeLibs="false" con las .so comprimidas |
zipalign -c -P 16 4, y comprobar compress_type de las entradas lib/ |
| Arranca y se cierra sin traza | La aplicación consulta sus propios splits en ejecución | §9.1. No tiene arreglo dentro del alcance de este corpus |
El dato que acota el problema: cruzando todas las rutas de todos los splits de cuatro contenedores
del corpus, los conflictos reales son como mucho seis ficheros —manifiesto, tabla, los tres de
firma y classes.dex con feature modules—; nada de res/, lib/ ni assets/ colisiona con
contenido distinto (Fusión de splits, §2.2).
8. Formatos
8.1 El fichero no es lo que dice ser (reproducido)
| Qué pasa | aapt2 dice |
apksigner dice |
|---|---|---|
No es un ZIP |
error: failed opening zip: Invalid file. |
ApkFormatException: Malformed APK: not a ZIP archive |
Es un ZIP sin AndroidManifest.xml |
error: could not identify format of APK. |
ApkFormatException: Missing AndroidManifest.xml |
La segunda fila aparece constantemente al pasar el contenedor —un .xapk, un .apkm— a una
herramienta que espera un APK; la detección estructural del paso 0 de
Pipeline de análisis lo resuelve antes de llegar aquí.
8.2 resources.arsc que no parsea (reproducido)
Provocado inflando el campo size del chunk raíz, y truncando el fichero:
size_grande.apk: error: corrupt resources.arsc: chunk's data extends past the end of the document (type=02 header_size=12 size=4572644).
truncado.apk: error: corrupt resources.arsc: chunk's data extends past the end of the document (type=02 header_size=12 size=3572644).
Un chunk declara un tamaño mayor que lo que queda de fichero: la misma familia de fallo que las
issues de apktool de §5.2, y el mensaje da los tres campos de la cabecera, que es lo que hace
falta para localizarlo con xxd. Lo que aapt2 tolera y sorprende: con packageCount = 99 en un
fichero de un paquete, aapt2 dump resources lo lee entero sin protestar —su lector no confía
en ese contador, recorre hasta que se acaban los datos—. Un lector propio que sí confíe en él leerá
fuera de rango.
El caso legítimo que rompe lectores estrictos: cinco splits del SAI de Netflix traen un
resources.arsc de 40 bytes exactos:
00000000: 0200 0c00 2800 0000 0000 0000 0100 1c00 ....(...........
00000010: 1c00 0000 0000 0000 0000 0000 0001 0000 ................
00000020: 1c00 0000 0000 0000 ........
RES_TABLE_TYPE = 0x0002, headerSize = 12, size = 40, packageCount = 0, seguido de un
string pool vacío de 28 bytes. Es una tabla válida: aapt2 dump resources responde solo
Binary APK y sale con 0. Pero rompe cualquier lector que asuma al menos un paquete. Y en el mismo
contenedor, split_voip.apk no tiene resources.arsc en absoluto.
8.3 AXML malformado (reproducido)
Los tres mensajes salen del mismo código de AOSP (ResourceType.cpp) que usa el dispositivo, así
que reproducirlos con aapt2 predice lo que dirá el instalador:
| Provocado | Salida literal |
|---|---|
size del chunk raíz mayor que el fichero |
W ResourceType: Bad XML block: header size 8 or total size 25572 is larger than data size 21476 |
| Fichero truncado a la mitad | W ResourceType: Bad XML block: header size 8 or total size 21476 is larger than data size 10738 |
Tipo del chunk raíz cambiado a 0x00FF |
W ResourceType: Bad XML block: expected root block type 3, got 255 |
Los tres van seguidos de <fichero>: error: failed to parse binary AndroidManifest.xml: failed to initialize ResXMLTree., que en el dispositivo es INSTALL_PARSE_FAILED_BAD_MANIFEST o …_MALFORMED.
8.4 DEX con checksum inválido (reproducido)
Corrompiendo los bytes 8 a 11 —el Adler-32— de un classes.dex del corpus y volviendo a ejecutar
dexdump -f:
E dexdump : dexdump.cc:2037 Failure to verify dex file 'checksum_malo.dex': Bad checksum (73027441, expected efbeadde)
Cómo se lee. El primer número es el checksum calculado sobre el contenido; el segundo,
precedido de expected, es el que estaba escrito en la cabecera — la redacción es
contraintuitiva, porque expected es lo que el fichero afirma, no lo que debería ser.
El detalle que enseña la estructura. Corrompiendo en cambio la signature SHA-1 —bytes 12 a 31—
el mensaje es también de checksum, Bad checksum (709a6bcb, expected 73027441), porque el
Adler-32 cubre todo lo que va detrás del byte 11, incluida la signature: tocar la firma rompe
primero el checksum. Y con la magic rota, Expected valid zip or dex file. Aparece al editar un
DEX a mano con un editor hexadecimal sin recalcular la cabecera — el ensamblador smali la
recalcula solo; un sed sobre el binario, no.
9. Síntomas de protección activa que se confunden con errores de herramienta
Los cuatro comparten una propiedad: el pipeline no falla en ningún paso y el problema aparece en ejecución. Aquí se detectan y se informan; neutralizarlos está fuera del alcance de este corpus, y el mecanismo de cada uno está en Anti-análisis y hardening y Packers.
9.1 · La aplicación instala, arranca y se cierra. No es un fallo del reempaquetado: el APK
verifica, alinea e instala. Suele ser una comprobación de integridad en ejecución: la aplicación
compara la huella SHA-256 de su propio certificado —vía
PackageManager.getPackageInfo(..., GET_SIGNING_CERTIFICATES)— contra una constante, o el digest de
una entrada del ZIP, o consulta una atestación remota. Refirmar cambia la huella por
construcción, así que la comprobación falla siempre, y que cambió se ve con
apksigner verify --print-certs sobre el original y sobre el modificado. Otra variante: un APK
fusionado en el que la aplicación consulta sus propios splits
(ApplicationInfo.splitSourceDirs, splitNames, SplitInstallManager) y los encuentra vacíos —la
issue #211 de APKEditor, abierta desde septiembre de 2025 sin respuesta, recoge una veintena de
aplicaciones fusionadas desde Play que caen con segfault en libpairipcore.so en Android 14 y 15.
9.2 · Funciona en emulador y no en dispositivo, o al revés. Detección de entorno:
anti-emulador —ro.product.model, ro.kernel.qemu, /dev/qemu_pipe, el número de serie, los
sensores— o, al revés, anti-debug/anti-root que solo se dispara en el dispositivo real. Los
indicadores sobreviven a la ofuscación porque son cadenas que llegan al sistema, así que
dexdump -d classes.dex | grep -oE "ro\.kernel\.qemu|/dev/qemu_pipe|goldfish|TracerPid" basta.
9.3 · Decompila, pero el código no tiene sentido. Cuatro causas que hay que separar antes de sacar conclusiones:
| Lo que se ve | Causa | Cómo se distingue |
|---|---|---|
Métodos con Code decompiled incorrectly o JADX ERROR |
Límite del decompilador | El marcador está ahí y se ve. Es §6 |
La aplicación habla por red y no hay ni una URL en el DEX |
Cifrado de strings de un ofuscador comercial | dexdump -d | grep -oE 'https?://…' no devuelve casi nada |
Todo el flujo es un switch gigante dentro de un while |
Aplanamiento de control de flujo | La estructura es uniforme en muchos métodos a la vez |
classes.dex minúsculo, un .so grande y un assets/ opaco |
Packer: lo decompilado es el stub | §6.4 de Pipeline de análisis |
La regla. Antes de concluir «este código es raro» hay que descartar que el problema sea el decompilador con el recuento de §6.6: un método marcado como incoherente no es evidencia de nada.
9.4 · Funciona la primera vez y luego no. Un packer que descifra el payload y lo cachea, o una
atestación remota que ya ha reportado el dispositivo. Lo relevante es lo negativo: no es un fallo
de reempaquetado, porque un APK mal reempaquetado falla de forma determinista.
10. Árbol de diagnóstico
¿QUÉ HA PASADO?
│
├─▶ NO INSTALA ───────────────────────────────────────────────────
│ ¿el mensaje empieza por INSTALL_PARSE_FAILED_?
│ sí → el fichero no se pudo leer §2.2
│ NO_CERTIFICATES / INCONSISTENT_CERT ─▶ firma §3
│ MANIFEST_MALFORMED ─▶ ¿atributos de split? §2.3
│ RESOURCES_ARSC_COMPRESSED ─▶ nada local lo ve §2.3
│ no → el sistema lo rechaza §2.4
│ UPDATE_INCOMPATIBLE ─▶ refirmado: desinstalar
│ MISSING_SPLIT ─▶ install-multiple, o sanear manifiesto
│ NO_MATCHING_ABIS ─▶ falta el split de ABI
│ ¿ni siquiera llega a un código INSTALL_*? ─▶ apksigner §3.1
│
├─▶ INSTALA Y PETA ───────────────────────────────────────────────
│ ¿arranca y se cierra sin traza? ─▶ integridad en ejec. §9.1
│ ¿muere en System.loadLibrary? ─▶ .so comprimidas §7
│ ¿NoClassDefFoundError? ─▶ DEX mal renumerado §7
│ ¿falla solo la pantalla parcheada? ─▶ verificación de ART:
│ banco de registros
│ (02-modificación §5.2)
│ ¿faltan textos o iconos? ─▶ tabla sin fusionar §7
│ ¿va en emulador y no en real? ─▶ detección de entorno §9.2
│
├─▶ NO DECOMPILA / NO DESEMPAQUETA ───────────────────────────────
│ apktool "Could not find framework resources" ─▶ apktool if §5.2
│ "Could not decode arsc file" ─▶ -r, o APKEditor
│ "Execution failed (exit code = 1)" ─▶ log de aapt2 §5.3
│ jadx exit 2, "No classes for decompile" ─▶ ¿es un APK? §8.1
│ OutOfMemoryError o cuelgue ─▶ -Xmx, -j §6.5
│ aapt2 "could not identify format of APK" ─▶ es el contenedor §8.1
│ "corrupt resources.arsc" §8.2 · "ResXMLTree" §8.3
│
└─▶ DECOMPILA MAL ────────────────────────────────────────────────
PRIMERO: contar los marcadores §6.2, §6.6
¿jadx salió con 3? → hay huecos, y sabe cuántos
¿"Code decompiled incorrectly"? → ese Java puede mentir §6.3
¿el .java entero es una traza de pila? → clase fallida §6.4
descartado el decompilador:
¿ni una URL en el DEX? ─▶ strings cifrados §9.3
¿switch gigante en todos lados? ─▶ flujo aplanado §9.3
¿DEX minúsculo + .so grande? ─▶ packer: es el stub §9.3
¿nombres a.b.c? ─▶ R8: buscar mapping.txt
Fuentes
Todas las URL se consultaron el 12 de agosto de 2026. Los ficheros de AOSP son de la rama main
y cuelgan de https://android.googlesource.com/platform/frameworks/base/+/refs/heads/main/,
descargados con ?format=TEXT y decodificados.
- AOSP —
core/java/android/content/pm/PackageManager.java· https://android.googlesource.com/platform/frameworks/base/+/refs/heads/main/core/java/android/content/pm/PackageManager.java · íntegras las tablas de §2.2 y §2.4 con sus valores y descripciones, la marca@hidede todos, y la comprobación de queINSTALL_FAILED_MULTI_ARCH_NOT_SUPPORTEDno existe. - AOSP — los cinco ficheros que producen los errores de §2.3 y §2.4, bajo la misma raíz:
core/java/android/content/pm/parsing/ApkLiteParseUtils.java(sitios y mensajes deNOT_APK,BAD_MANIFEST,UNEXPECTED_EXCEPTIONyMANIFEST_MALFORMED);core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java(las reglas devalidateName()y el límite de 223 caracteres);core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.javajunto acore/java/android/content/pm/parsing/result/ParseInput.java(el error diferidoRESOURCES_ARSC_COMPRESSED, suChangeId 132742131con@EnabledAfter(targetSdkVersion = Q)y el texto del error);core/java/android/util/apk/ApkSignatureVerifier.java(NO_CERTIFICATESeINCONSISTENT_CERTIFICATES); yservices/core/java/com/android/server/pm/conPackageInstallerSession.java,InstallPackageHelper.javayPackageManagerServiceUtils.java(MISSING_SPLIT,UPDATE_INCOMPATIBLEyVERSION_DOWNGRADE, incluido elTODOdel propio AOSP sobre la reutilización del segundo). - jadx — código fuente, commit
e738a26del 5 de agosto de 2026, repositorio clonado y leído directamente:codegen/MethodGen.java,codegen/utils/CodeGenUtils.java,dex/attributes/nodes/JadxCommentsAttr.java,dex/nodes/ClassNode.java,utils/ErrorsCounter.javayjadx-cli/…/JadxCLI.java· https://github.com/skylot/jadx/blob/master/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java · todos los literales de §6.2, el mecanismo de tres niveles de §6.3, el comportamiento de clase fallida de §6.4 y los códigos de salida de §6.6. - jadx — issues cerradas #2676 y #2744 · https://github.com/skylot/jadx/issues/2676 · las explicaciones de causa raíz de skylot sobre el consumo de memoria por error-por-instrucción y el desbordamiento de pila en la inferencia de tipos (§6.5), citadas literalmente.
- Apktool — código fuente, commit
79b6338del 10 de agosto de 2026 (ramamain, 3.x), repositorio clonado · https://github.com/iBotPeaches/Apktool/tree/main/brut.apktool/apktool-lib/src/main/java/brut/androlib/exceptions ybrut.j.util/src/main/java/brut/util/OS.java· la tabla de §5.2, el mensajeExecution failed (exit code = …)de §5.3, el uso de--legacy,Legacy aapt is no longer supported.y la comprobación por inspección de que apktool no alinea (§5.4). - Apktool — tags
v2.7.0yv2.9.3· https://raw.githubusercontent.com/iBotPeaches/Apktool/v2.7.0/brut.apktool/apktool-lib/src/main/java/brut/androlib/err/CantFindFrameworkResException.java · las cadenas 2.x de §5.1. - Apktool — issues cerradas #3036, #2989, #2824, #2836, #3199 y #3298 ·
https://github.com/iBotPeaches/Apktool/issues/3036 · las explicaciones de causa raíz de
iBotPeaches sobre tamaños de chunk mentirosos, entradas duplicadas y tablas sparse (§5.2, §5.3).
La ausencia de
--force-manual-sizese verificó sobre los 2.376 commits de todas las ramas y sobre https://apktool.org/docs/cli-parameters/. - Apktool — FAQ oficial · https://apktool.org/docs/faq/ · las citas literales de §5.4.
- Ejecuciones locales sobre el corpus — 12 de agosto de 2026 con
build-tools37.0.0 (apksigner0.9,zipalign,aapt22.20-15087165,dexdump), OpenJDK 21.0.10 y Python 3.12.10 sobre macOS Darwin 25.5.0. De aquí salen todos los mensajes marcados (reproducido): §2.3, §3.2 a §3.5, §4.1, §4.2 y §8.1 a §8.4. Provocados sobre copias deorg.fossify.calculator_1.4.0.apky sobrecom.netflix.mediaclient.sai.zipen el scratchpad. En ningún momento se ha escrito en el corpus. - Documentos de este corpus · Alineación y zipalign (§4.1, §4.3), Esquemas v1, v2 y v3 (§3.3), Formato DEX (§8.4), Tabla de recursos (§8.2) y Decompiladores a Java (§6.1, cuya sección 3.5 este documento corrige) y Comparativa y selección (§4.3, el reparto de esquemas de firma entre las trece herramientas, citado en §3.3).