{"record":{"id":"b5f4dfee1ffc69e0","repo":"NationalSecurityAgency/ghidra","slug":"cannot-parse-step","errorCode":null,"errorMessage":"Cannot parse step: '","messagePattern":"Cannot parse step: '","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/PatchStep.java","lineNumber":196,"sourceCode":"\t\t\t\tregister = register.getBaseRegister();\n\t\t\t}\n\t\t\tint length = register.getNumBytes();\n\t\t\tarray.getData(register.getOffset(), data, 0, length);\n\t\t\tBigInteger value = Utils.bytesToBigInteger(data, length, language.isBigEndian(), false);\n\t\t\tif (register.isProgramCounter()) {\n\t\t\t\tresult.add(String.format(\"goto 0x%s\", value.toString(16)));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tresult.add(String.format(\"%s=0x%s\", register, value.toString(16)));\n\t\t\t}\n\t\t\tremains.remove(spanOfRegister(register));\n\t\t}\n\t}\n\n\tpublic static PatchStep parse(long threadKey, String stepSpec) {\n\t\t// Would be nice to parse and validate the sleigh here, but need a language.\n\t\tif (!stepSpec.startsWith(\"{\") || !stepSpec.endsWith(\"}\")) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot parse step: '\" + stepSpec + \"'\");\n\t\t}\n\t\treturn new PatchStep(threadKey, stepSpec.substring(1, stepSpec.length() - 1));\n\t}\n\n\tpublic PatchStep(long threadKey, String sleigh) {\n\t\tthis.threadKey = threadKey;\n\t\tthis.sleigh = Objects.requireNonNull(sleigh);\n\t\tthis.hashCode = Objects.hash(threadKey, sleigh);\n\t}\n\n\tprivate void setSleigh(String sleigh) {\n\t\tthis.sleigh = sleigh;\n\t\tthis.hashCode = Objects.hash(threadKey, sleigh);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn hashCode;","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/PatchStep.java#L178-L214","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the stepSpec is wrapped in curly braces, e.g. '{r0=0x1234}'","If building the spec dynamically, wrap with braces: '{' + sleighCode + '}'","Use TraceSchedule.snap() or TraceSchedule.parse() with the full well-formed schedule string instead of constructing PatchStep directly","Validate the spec with stepSpec.startsWith(\"{\") && stepSpec.endsWith(\"}\") before calling parse"],"exampleFix":"// before\nPatchStep.parse(1, \"r0=0x1234\");\n// after\nPatchStep.parse(1, \"{r0=0x1234}\");","handlingStrategy":"validation","validationCode":"boolean isValidPatchSpec(String stepSpec) {\n    return stepSpec != null\n        && stepSpec.startsWith(\"{\")\n        && stepSpec.endsWith(\"}\")\n        && stepSpec.length() >= 2;\n}","typeGuard":"// N/A — string validation, not type narrowing","tryCatchPattern":"try {\n    PatchStep step = PatchStep.parse(threadKey, stepSpec);\n} catch (IllegalArgumentException e) {\n    // log and prompt user for corrected Sleigh spec\n}","preventionTips":["Always wrap Sleigh code in braces when building patch specs","Use Step.parse as the entry point — it routes to PatchStep only when '{' is detected","When building specs programmatically, use a helper that enforces braces"],"tags":["ghidra","trace-schedule","sleigh","patch-step","input-validation"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}