oracle/graal · error · InternalError
Unable to decode some instructions in
Error message
Unable to decode some instructions in
What it means
This InternalError is thrown in DisassemblerTool's decode loop when a decode step fails and the fallback byte-emission path cannot determine a skip size because the disassembler's architecture is neither AArch64 nor AMD64. On AMD64 broken instructions are resynchronized one byte at a time and on AArch64 four bytes at a time; any other Architecture enum value has no resynchronization policy, so the tool aborts. In practice it marks an internal inconsistency: a Disassembler was constructed for an architecture the tool's repair logic does not know.
Source
Thrown at compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/disassembler/DisassemblerTool.java:388
for (DecodedInstruction insn : allInsn) {
int insnOffset = (int) (insn.address() - startAddress);
instructions.add(new DisassemblerTool.Instruction(insnOffset, insn, getOperandComments(operandComments, insn.size(), insnOffset), getComments(comments, insnOffset)));
currentOffset = insnOffset + insn.size();
}
if (currentOffset >= endOffset) {
break;
} else {
int size;
// Broken instruction
if (dis.getArchitecture().equals(Disassembler.Architecture.AArch64)) {
size = 4;
} else if (dis.getArchitecture().equals(Disassembler.Architecture.AMD64)) {
// This could potentially be handled better by splitting the machine code into
// chunks in between comments and decoding those chunks independently. That
// would naturally resynchronize the disassembly if problems are encountered.
size = 1;
} else {
throw new InternalError("Unable to decode some instructions in " + dis.getArchitecture());
}
byte[] bytes = Arrays.copyOfRange(code, currentOffset, currentOffset + size);
Formatter buf = new Formatter();
for (byte b : bytes) {
buf.format("%02x ", b);
}
String encoding = (size == 1 ? ".byte\t" : ".bytes\t") + buf.toString().trim();
DecodedInstruction insn = new DecodedInstruction(startAddress + currentOffset, size, encoding, null, bytes);
instructions.add(new DisassemblerTool.Instruction(currentOffset, insn,
getOperandComments(operandComments, size, currentOffset), getComments(comments, currentOffset + startOffset)));
currentOffset += size;
}
}
return instructions;
}
private static List<String> getComments(Map<Integer, List<String>> comments, int insnOffset) {
if (comments != null) {View on GitHub (pinned to a66e9ccd1d)
Solutions
- If you added a new Architecture constant, add a resync size case for it in DisassemblerTool's broken-instruction branch.
- If using a custom Disassembler, make it report AMD64 or AArch64 (whichever matches its decoding) so the fallback applies.
- Fix the undecodable bytes upstream (regenerate the hex dump) so the failure branch is never entered.
- Report it as a GraalVM bug if it occurs with an unmodified build — it indicates a tool/architecture mismatch.
Example fix
// before
} else {
throw new InternalError("Unable to decode some instructions in " + dis.getArchitecture());
}
// after (when adding RISCV64 support)
} else if (dis.getArchitecture().equals(Disassembler.Architecture.RISCV64)) {
size = 4;
} else {
throw new InternalError("Unable to decode some instructions in " + dis.getArchitecture());
} Defensive patterns
Strategy: validation
Validate before calling
Disassembler.Architecture a = dis.getArchitecture();
if (a != Disassembler.Architecture.AMD64 && a != Disassembler.Architecture.AArch64) {
throw new UnsupportedOperationException("no resync policy for " + a);
} Try / catch
try { decode(); } catch (InternalError e) { /* treat as tool limitation: report arch, fall back to raw hex dump */ } Prevention
- Keep the Architecture enum and this resync switch in sync when extending the enum.
- Custom Disassemblers should report one of the two supported constants.
- Undecodable bytes reaching this branch usually means upstream data corruption — fix the dump.
When it happens
Trigger: A Disassembler.Architecture value outside {AArch64, AMD64} reaches decodeInstructions and encounters an instruction the underlying decoder fails on (broken/undecodable bytes). The size-selection if/else falls to the default branch and throws.
Common situations: New Architecture enum constants added without updating this repair switch, or a custom Disassembler implementation returning an unusual architecture constant. Not reachable on stock x86_64/aarch64 builds even with corrupt code bytes.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Unexpected architecture ${architecture}
- Unexpected architecture name ${archName}
- Unknown replay architecture kind
- Unknown replay register config kind ${kind}
- Register not found
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/c778c97730d6d417.
Report an issue: GitHub.