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

  1. If you added a new Architecture constant, add a resync size case for it in DisassemblerTool's broken-instruction branch.
  2. If using a custom Disassembler, make it report AMD64 or AArch64 (whichever matches its decoding) so the fallback applies.
  3. Fix the undecodable bytes upstream (regenerate the hex dump) so the failure branch is never entered.
  4. 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

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

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/c778c97730d6d417. Report an issue: GitHub.