NationalSecurityAgency/ghidra · error · AssemblyException
Could not assemble: %s
Error message
Could not assemble: %s
What it means
Thrown by AbstractPatchAssemblyCommand.assemble() when AssemblyBuffer.assemble(line) fails for one instruction line. The original AssemblySyntaxException (malformed/unknown mnemonic or operand) or AssemblySemanticException (valid syntax but impossible encoding, e.g. bad register or out-of-range immediate) is wrapped in an AssemblyException whose message is 'Could not assemble: <line>'. Note: only raw instruction text is supported here; the source comment marks data directives and label placement as unimplemented.
Source
Thrown at Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/AbstractPatchAssemblyCommand.java:74
public AddressSetView assemble(T program, TaskMonitor monitor)
throws CancelledException, IOException, MemoryAccessException, AssemblyException {
monitor.setMessage("Constructing Assembler");
monitor.checkCancelled();
AssemblyBuffer buf = new AssemblyBuffer(asm, entry, initialContext);
monitor.initialize(lines.size(), "Assembling");
for (String line : lines) {
if (line.isBlank()) {
continue;
}
// LATER: Data directives? Label placement?
try {
buf.assemble(line);
monitor.increment();
}
catch (AssemblySyntaxException | AssemblySemanticException e) {
throw new AssemblyException("Could not assemble: %s".formatted(line), e);
}
}
monitor.initialize(0, "Placing bytes");
monitor.checkCancelled();
AddressSet set = new AddressSet(entry, buf.getNext().previous());
// Get the command before we modify the memory/listing, so it can inspect things
Command<T> dis = newDisassembleCommand(set, program);
program.getListing()
.clearCodeUnits(set.getMinAddress(), set.getMaxAddress(), true, monitor);
program.getMemory().setBytes(entry, buf.getBytes());
monitor.setMessage("Disassembling");
monitor.checkCancelled();
// Might not succeed...
dis.applyTo(program);View on GitHub (pinned to d5f144c24d)
Solutions
- Read the offending line from the message after 'Could not assemble: ' and correct the typo / operand count.
- Confirm the instruction is valid for the program's processor language and that the assembler was built for that language (Assemblers.getAssemblerForLanguage(program.getLanguage())).
- Switch the operand/register to a form the language encodes (e.g. different immediate width, valid register name, supported addressing mode); consult the Sleigh / processor reference.
- Split multi-instruction input into one line per instruction and assemble line-by-line to isolate which line fails, since the exception reports only the first failing line.
- If no line assembles at all, the language may lack an assembler spec; verify the language ships assembly templates before attempting patch assembly.
Example fix
// before - typo + wrong-syntax instruction for the target language String bad = "mvo rax, 0x1"; // 'mvo' is not a valid mnemonic // after - correct mnemonic and operands for x86:LE:64:default String good = "mov rax, 0x1";
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-assemble each line into a throwaway AssemblyBuffer before
// committing patches to the real program, to localize the failure.
AssemblyBuffer probe = new AssemblyBuffer(asm, entry, initialContext);
java.util.List<String> problems = new java.util.ArrayList<>();
for (String line : lines) {
if (line.isBlank()) continue;
try {
probe.assemble(line);
} catch (AssemblySyntaxException | AssemblySemanticException e) {
problems.add(line + " <- " + e.getMessage());
}
} Try / catch
// applyTo() already catches AssemblyException and stores its message in
// status (command returns false). For direct assemble() use, catch
// AssemblyException and read the offending line from the message.
try {
cmd.assemble(program, monitor);
} catch (AssemblyException e) {
String msg = e.getMessage(); // "Could not assemble: <line>"
String line = msg.substring(msg.indexOf(':') + 1).trim();
Throwable cause = e.getCause(); // AssemblySyntax|SemanticException
// surface line + cause to the user; do NOT silently retry unchanged input
} Prevention
- Build the Assembler for the exact program language: Assemblers.getAssemblerForLanguage(program.getLanguage()).
- Feed one instruction per line; the patch assembler does not support labels or data directives yet.
- When pasting assembly, confirm the dialect (Intel/AT&T, suffix conventions) matches what the Sleigh assembler accepts.
- Assemble line-by-line in a probe buffer first so the user sees every failing line, not just the first.
When it happens
Trigger: Calling the patch assembler (single-line or multi-line) where at least one line is: an unknown/unsupported mnemonic for the program's processor/Sleigh language, has the wrong number of operands, references a register that does not exist for the language, uses an immediate outside the encodable range, uses the wrong assembly syntax for the architecture, or contains a label/data directive the assembler does not understand.
Common situations: Typo in an instruction; pasting x86 syntax into an ARM (or vice versa) program; using AT&T vs Intel form when the language expects the other; an instruction the Sleigh assembler does not encode for that language variant; encoding-dependent operand (e.g. conditional suffix, addressing mode) not supported; whitespace/blank handling confusion (note: truly blank lines are skipped).
Related errors
- Current trace does not use Sleigh
- Cannot parse step: '
- No match found
- Unsupported value: {}
- Invalid value for {}
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/8bb710ce2a399520.
Report an issue: GitHub.