NationalSecurityAgency/ghidra · error · IllegalArgumentException

Cannot parse step: '

Error message

Cannot parse step: '

What it means

PatchStep.parse rejects a step specification that is not brace-enclosed Sleigh code. The parser requires the spec to start with '{' and end with '}', stripping those delimiters to obtain the raw Sleigh statement. If either delimiter is missing, the input is not a valid patch step and the exception is thrown. This is the patch sub-parser of the schedule stepping DSL — it patches emulator machine state at a point in time.

Source

Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/PatchStep.java:196

				register = register.getBaseRegister();
			}
			int length = register.getNumBytes();
			array.getData(register.getOffset(), data, 0, length);
			BigInteger value = Utils.bytesToBigInteger(data, length, language.isBigEndian(), false);
			if (register.isProgramCounter()) {
				result.add(String.format("goto 0x%s", value.toString(16)));
			}
			else {
				result.add(String.format("%s=0x%s", register, value.toString(16)));
			}
			remains.remove(spanOfRegister(register));
		}
	}

	public static PatchStep parse(long threadKey, String stepSpec) {
		// Would be nice to parse and validate the sleigh here, but need a language.
		if (!stepSpec.startsWith("{") || !stepSpec.endsWith("}")) {
			throw new IllegalArgumentException("Cannot parse step: '" + stepSpec + "'");
		}
		return new PatchStep(threadKey, stepSpec.substring(1, stepSpec.length() - 1));
	}

	public PatchStep(long threadKey, String sleigh) {
		this.threadKey = threadKey;
		this.sleigh = Objects.requireNonNull(sleigh);
		this.hashCode = Objects.hash(threadKey, sleigh);
	}

	private void setSleigh(String sleigh) {
		this.sleigh = sleigh;
		this.hashCode = Objects.hash(threadKey, sleigh);
	}

	@Override
	public int hashCode() {
		return hashCode;

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Ensure the stepSpec is wrapped in curly braces, e.g. '{r0=0x1234}'
  2. If building the spec dynamically, wrap with braces: '{' + sleighCode + '}'
  3. Use TraceSchedule.snap() or TraceSchedule.parse() with the full well-formed schedule string instead of constructing PatchStep directly
  4. Validate the spec with stepSpec.startsWith("{") && stepSpec.endsWith("}") before calling parse

Example fix

// before
PatchStep.parse(1, "r0=0x1234");
// after
PatchStep.parse(1, "{r0=0x1234}");
Defensive patterns

Strategy: validation

Validate before calling

boolean isValidPatchSpec(String stepSpec) {
    return stepSpec != null
        && stepSpec.startsWith("{")
        && stepSpec.endsWith("}")
        && stepSpec.length() >= 2;
}

Type guard

// N/A — string validation, not type narrowing

Try / catch

try {
    PatchStep step = PatchStep.parse(threadKey, stepSpec);
} catch (IllegalArgumentException e) {
    // log and prompt user for corrected Sleigh spec
}

Prevention

When it happens

Trigger: Calling PatchStep.parse(threadKey, stepSpec) or TraceSchedule.parse with a schedule whose step component contains a '{' prefix but no matching '}', or vice versa, or a completely un-braced string that gets routed to the patch branch. Also triggered indirectly via Step.parse when stepSpec starts with '{' but lacks the closing brace.

Common situations: Manually building a schedule string like '0:t1-{r0=0x1234' (missing closing brace), or programmatically concatenating Sleigh fragments without ensuring the braces are present. Copy-paste errors when constructing trace schedule specs from examples.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/b5f4dfee1ffc69e0. Report an issue: GitHub.