{"record":{"id":"fc1e9b5b4d423a3c","repo":"Tencent/tinker","slug":"bad-oat-version-fc1e9b","errorCode":null,"errorMessage":"Bad oat version: {}","messagePattern":"Bad oat version: (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareOatUtil.java","lineNumber":85,"sourceCode":"                    || oatMagicAndVersion[3] != '\\n') {\n                throw new IOException(\n                        String.format(\"Bad oat magic: %x %x %x %x\",\n                                oatMagicAndVersion[0],\n                                oatMagicAndVersion[1],\n                                oatMagicAndVersion[2],\n                                oatMagicAndVersion[3])\n                );\n            }\n\n            final int versionOffsetFromOatBegin = 4;\n            final int versionBytes = 3;\n\n            final String oatVersion = new String(oatMagicAndVersion,\n                    versionOffsetFromOatBegin, versionBytes, Charset.forName(\"ASCII\"));\n            try {\n                Integer.parseInt(oatVersion);\n            } catch (NumberFormatException e) {\n                throw new IOException(\"Bad oat version: \" + oatVersion);\n            }\n\n            ByteBuffer buffer = ByteBuffer.allocate(128);\n            buffer.order(elfFile.getDataOrder());\n            // TODO This is a risk point, since each oat version may use a different offset.\n            // So far it's ok. Perhaps we should use oatVersionNum to judge the right offset in\n            // the future.\n            final int isaNumOffsetFromOatBegin = 12;\n            channel.position(roDataHdr.shOffset + isaNumOffsetFromOatBegin);\n            buffer.limit(4);\n            ShareElfFile.readUntilLimit(channel, buffer, \"Failed to read isa num.\");\n\n            int isaNum = buffer.getInt();\n            if (isaNum < 0 || isaNum >= InstructionSet.values().length) {\n                throw new IOException(\"Bad isa num: \" + isaNum);\n            }\n\n            switch (InstructionSet.values()[isaNum]) {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareOatUtil.java#L67-L103","documentation":"ShareOatUtil reads the 3 ASCII version bytes at offset 4 of the oat header and requires them to parse as an integer (e.g. '007', '064'). NumberFormatException triggers IOException(\"Bad oat version: <str>\"). The oat header exists but its version field is not a recognizable OAT version.","triggerScenarios":"getOatFileInstructionSet on an odex whose .rodata starts with 'oat\\n' but whose following 3 bytes are not digits — format change across ART versions or corruption.","commonSituations":"ART version layout changes on newer Android releases (the code itself carries a TODO about version-dependent offsets); custom ROMs; partially corrupted odex files.","solutions":["Verify the oat version bytes with a hex dump of .rodata offset 4..7.","Fall back to Build.CPU_ABI-derived instruction set when parsing fails.","Update Tinker to a release that supports the device's ART version.","Catch Throwable from getOatFileInstructionSet and degrade gracefully."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    isa = ShareOatUtil.getOatFileInstructionSet(odexFile);\n} catch (IOException ioe) {\n    // 'Bad oat version': unsupported oat version, fall back to ABI-derived ISA\n    isa = ShareTinkerInternals.getCurrentInstructionSet();\n}","preventionTips":["Track oat header changes per Android release when supporting new versions.","Always provide an instruction-set fallback when probing odex files.","Report unknown oat versions (log the parsed string) to catch format drift early."],"tags":["android","tinker","oat","version","instruction-set"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}