Tencent/tinker · error · IOException
Bad isa num: {}
Error message
Bad isa num: {} What it means
ShareOatUtil reads the instruction-set number at offset 12 of the oat header and indexes the InstructionSet enum with it. If the int is negative or >= InstructionSet.values().length it throws IOException("Bad isa num: <n>"). The value read is not a valid InstructionSet ordinal, meaning the oat header layout differs from what the parser assumes or the file is corrupt.
Source
Thrown at tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareOatUtil.java:100
try {
Integer.parseInt(oatVersion);
} catch (NumberFormatException e) {
throw new IOException("Bad oat version: " + oatVersion);
}
ByteBuffer buffer = ByteBuffer.allocate(128);
buffer.order(elfFile.getDataOrder());
// TODO This is a risk point, since each oat version may use a different offset.
// So far it's ok. Perhaps we should use oatVersionNum to judge the right offset in
// the future.
final int isaNumOffsetFromOatBegin = 12;
channel.position(roDataHdr.shOffset + isaNumOffsetFromOatBegin);
buffer.limit(4);
ShareElfFile.readUntilLimit(channel, buffer, "Failed to read isa num.");
int isaNum = buffer.getInt();
if (isaNum < 0 || isaNum >= InstructionSet.values().length) {
throw new IOException("Bad isa num: " + isaNum);
}
switch (InstructionSet.values()[isaNum]) {
case kArm:
case kThumb2:
result = "arm";
break;
case kArm64:
result = "arm64";
break;
case kX86:
result = "x86";
break;
case kX86_64:
result = "x86_64";
break;
case kMips:
result = "mips";View on GitHub (pinned to 1b7ea02c23)
Solutions
- Hex-inspect the oat header around offset 12 for the device's ART version and confirm the field is where the parser expects.
- Use getCurrentInstructionSet() (ABI-based) as a fallback when oat parsing throws.
- Upgrade Tinker for newer Android support.
- Delete the odex to force regeneration, then retry.
Defensive patterns
Strategy: fallback
Try / catch
try {
isa = ShareOatUtil.getOatFileInstructionSet(odexFile);
} catch (IOException ioe) {
// 'Bad isa num': header layout mismatch, fall back to ABI-derived ISA
isa = ShareTinkerInternals.getCurrentInstructionSet();
} Prevention
- The isa offset (12) is version-sensitive; validate against each ART version you support.
- Always implement an ABI-based instruction-set fallback.
- Log the bad isa number to correlate with device/ART versions.
When it happens
Trigger: getOatFileInstructionSet where bytes at rodata offset 12 decode to an out-of-range int — oat version with different header layout (the code's TODO notes the offset risk), or a corrupted odex.
Common situations: Newer oat versions changing the isa field offset; unusual ABIs; corrupted odex produced or modified during OTA.
Related errors
- Unable to find .rodata section.
- Bad isa num: {}
- Unable to find .rodata section.
- Bad oat magic: %x %x %x %x
- Bad oat version: {}
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/989b2ec9801b4e4a.
Report an issue: GitHub.