{"record":{"id":"e2f1e194e98a640d","repo":"NationalSecurityAgency/ghidra","slug":"cannot-have-instructions-steps-following-p-code-st","errorCode":null,"errorMessage":"Cannot have instructions steps following p-code steps","messagePattern":"Cannot have instructions steps following p-code steps","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/TraceSchedule.java","lineNumber":892,"sourceCode":"\t * schedule contains any p-code steps and {@code next} has instruction steps, an error will be\n\t * \n\t * @param next the schedule to append. Its snap is ignored.\n\t * @return the complete schedule\n\t * @throws IllegalArgumentException if the result would have instruction steps following p-code\n\t *             steps\n\t */\n\tpublic TraceSchedule advanced(TraceSchedule next) {\n\t\tif (this.pSteps.isNop()) {\n\t\t\tSequence ticks = this.steps.clone();\n\t\t\tticks.advance(next.steps);\n\t\t\treturn new TraceSchedule(this.snap, ticks, next.pSteps.clone(), next.source);\n\t\t}\n\t\telse if (next.steps.isNop()) {\n\t\t\tSequence pTicks = this.pSteps.clone();\n\t\t\tpTicks.advance(next.pSteps);\n\t\t\treturn new TraceSchedule(this.snap, this.steps.clone(), pTicks, Source.INPUT);\n\t\t}\n\t\tthrow new IllegalArgumentException(\"Cannot have instructions steps following p-code steps\");\n\t}\n\n\t/**\n\t * Drop the p-code steps\n\t * \n\t * @return the schedule without ops\n\t */\n\tpublic TraceSchedule dropPSteps() {\n\t\treturn new TraceSchedule(this.snap, this.steps, new Sequence());\n\t}\n\n\t/**\n\t * Drop the last step\n\t * \n\t * <p>\n\t * If there are p-code steps, this drops the last step there. Otherwise, this drops the last\n\t * step from the instruction steps. A step includes all ticks in the step, e.g.,\n\t * {@code 0:t0-20;t1-5} becomes {@code 0:t0-20}. To remove a specific number of ticks, see","sourceCodeStart":874,"sourceCodeEnd":910,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/TraceSchedule.java#L874-L910","documentation":"TraceSchedule.advanced combines this schedule with a 'next' schedule to produce a continued schedule. If this schedule already has p-code steps (pSteps is non-empty), and the next schedule has instruction/tick steps (steps is non-empty), the combination is illegal — p-code steps cannot be followed by instruction steps because that would require emulating backwards from p-code to instruction level. Only p-code-after-p-code or instruction-after-instruction continuations are valid.","triggerScenarios":"Calling schedule.advanced(next) where schedule has pSteps and next has steps (instruction steps). This happens when you first advance into p-code stepping (the '.' portion) and then try to append an instruction-level step.","commonSituations":"Building composite schedules from multiple user actions where the user first steps at p-code level then tries to step at instruction level. Merging schedule bookmarks that were recorded at different emulation granularities. Attempting to create a schedule that mixes instruction and p-code steps in an invalid order.","solutions":["If this schedule has pSteps, only advance with a next schedule that also has only pSteps (next.steps must be nop)","Drop the pSteps from this schedule first: schedule = schedule.dropPSteps(), then advance","Restructure the schedule so all instruction steps come before all p-code steps","Use schedule.finishPcodeStep() or equivalent to normalize before advancing"],"exampleFix":"// before\nTraceSchedule base = TraceSchedule.parse(\"0:t1-5.t2-1\", Source.INPUT, TimeRadix.DEC);\nTraceSchedule next = TraceSchedule.parse(\"0:t1-3\", Source.INPUT, TimeRadix.DEC);\nTraceSchedule combined = base.advanced(next); // throws\n// after\nTraceSchedule base = TraceSchedule.parse(\"0:t1-5.t2-1\", Source.INPUT, TimeRadix.DEC);\nTraceSchedule next = TraceSchedule.parse(\"0:.t2-1\", Source.INPUT, TimeRadix.DEC); // pSteps only\nTraceSchedule combined = base.advanced(next);","handlingStrategy":"validation","validationCode":"boolean canAdvance(TraceSchedule base, TraceSchedule next) {\n    if (!base.pSteps.isNop() && !next.steps.isNop()) {\n        return false; // instruction steps after p-code steps\n    }\n    return true;\n}","typeGuard":"// N/A","tryCatchPattern":"try {\n    TraceSchedule combined = base.advanced(next);\n} catch (IllegalArgumentException e) {\n    // drop pSteps and retry, or restructure the schedule\n    TraceSchedule combined = base.dropPSteps().advanced(next);\n}","preventionTips":["Never mix instruction steps after p-code steps in a schedule","Check base.pSteps.isNop() or next.steps.isNop() before calling advanced","Use dropPSteps() to normalize before combining schedules"],"tags":["ghidra","trace-schedule","pcode-steps","precondition"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}