{"record":{"id":"2ec323a70a7b2d61","repo":"NationalSecurityAgency/ghidra","slug":"cannot-parse-step-2ec323","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/Step.java","lineNumber":62,"sourceCode":"\t * @param radix the radix\n\t * @return the parsed step\n\t * @throws IllegalArgumentException if the specification is of the wrong form\n\t */\n\tstatic Step parse(String stepSpec, TimeRadix radix) {\n\t\tif (\"\".equals(stepSpec)) {\n\t\t\treturn nop();\n\t\t}\n\t\tString[] parts = stepSpec.split(\"-\");\n\t\tif (parts.length == 1) {\n\t\t\treturn parse(-1, parts[0].trim(), radix);\n\t\t}\n\t\tif (parts.length == 2) {\n\t\t\tString tPart = parts[0].trim();\n\t\t\tif (tPart.startsWith(\"t\")) {\n\t\t\t\treturn parse(Long.parseLong(tPart.substring(1)), parts[1].trim(), radix);\n\t\t\t}\n\t\t}\n\t\tthrow new IllegalArgumentException(\"Cannot parse step: '\" + stepSpec + \"'\");\n\t}\n\n\t/**\n\t * Parse a step for the given thread key\n\t * \n\t * <p>\n\t * The form of the spec must either be numeric, indicating some number of ticks, or\n\t * brace-enclosed Sleigh code, e.g., {@code \"{r0=0x1234}\"}. The latter allows patching machine\n\t * state during execution.\n\t * \n\t * @param threadKey the thread to step, or -1 for the last thread or event thread\n\t * @param stepSpec the string specification\n\t * @param radix the radix\n\t * @return the parsed step\n\t * @throws IllegalArgumentException if the specification is of the wrong form\n\t */\n\tstatic Step parse(long threadKey, String stepSpec, TimeRadix radix) {\n\t\tif (stepSpec.startsWith(\"s\")) {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/Step.java#L44-L80","documentation":"Step.parse is the top-level dispatcher for a single step specification. It splits on '-', expecting either a single part (no thread prefix, defaults to -1/event thread) or two parts where the first starts with 't' followed by the thread key. If the split produces more than two parts, or two parts where the first does not start with 't', the spec is unparseable. This catches malformed step specs that don't match 'tickCount', 'tN-tickCount', 'sN', 'tN-sN', '{sleigh}', or 'tN-{sleigh}'.","triggerScenarios":"Passing a stepSpec with multiple dashes like 't1-2-3', or a two-part split where the first part doesn't start with 't' like '1-2'. Also when a Sleigh patch contains a dash character outside braces, causing an unexpected split.","commonSituations":"Sleigh code containing '-' (subtraction operator) in a patch step that is not brace-enclosed or where braces are malformed. Building step specs by string concatenation with incorrect separators. Schedule strings with corrupted or truncated step segments.","solutions":["Ensure the spec matches one of: 'N', 'tN-M', 'sN', 'tN-sN', '{sleigh}', 'tN-{sleigh}'","If using Sleigh with subtraction, ensure it is enclosed in braces: '{R0=R1-1}'","Use Step.parse(threadKey, stepSpec, radix) directly when the thread key is already known, bypassing the split logic","Validate the spec format before parsing with a regex like ^(t\\d+-)?(s?\\d+|\\{.*\\})$"],"exampleFix":"// before\nStep.parse(\"1-2\", radix); // ambiguous: no 't' prefix\n// after\nStep.parse(\"t1-2\", radix);","handlingStrategy":"validation","validationCode":"boolean isValidStepSpec(String stepSpec) {\n    // Form: N | tN-M | sN | tN-sN | {sleigh} | tN-{sleigh}\n    return stepSpec != null\n        && stepSpec.matches(\"^(t\\\\d+-)?(s?\\\\d+|\\\\{.*})$\");\n}","typeGuard":"// N/A","tryCatchPattern":"try {\n    Step step = Step.parse(stepSpec, radix);\n} catch (IllegalArgumentException e) {\n    // log the malformed spec and report to user\n}","preventionTips":["Ensure Sleigh code with '-' is always brace-enclosed","Follow the documented grammar: [t<key>-]<tick|skip|patch>","Use Step.parse(threadKey, stepSpec, radix) when key is known to bypass the split"],"tags":["ghidra","trace-schedule","step","input-validation"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}