{"record":{"id":"573a345e75e8165e","repo":"NationalSecurityAgency/ghidra","slug":"cannot-step-a-negative-number","errorCode":null,"errorMessage":"Cannot step a negative number","messagePattern":"Cannot step a negative number","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/AbstractStep.java","lineNumber":29,"sourceCode":" * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage ghidra.trace.model.time.schedule;\n\nimport java.util.List;\n\nimport ghidra.program.model.lang.Language;\nimport ghidra.trace.model.time.schedule.TraceSchedule.TimeRadix;\n\npublic abstract class AbstractStep implements Step {\n\tprotected final long threadKey;\n\tprotected long tickCount;\n\n\tprotected AbstractStep(long threadKey, long tickCount) {\n\t\tif (tickCount < 0) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot step a negative number\");\n\t\t}\n\t\tthis.threadKey = threadKey;\n\t\tthis.tickCount = tickCount;\n\t}\n\n\t/**\n\t * Return the step portion of {@link #toString()}\n\t * \n\t * @param radix the radix\n\t * @return the string\n\t */\n\tprotected abstract String toStringStepPart(TimeRadix radix);\n\n\t@Override\n\tpublic String toString() {\n\t\treturn toString(TimeRadix.DEFAULT);\n\t}\n","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/AbstractStep.java#L11-L47","documentation":"Thrown by the AbstractStep constructor when tickCount < 0. A step represents a non-negative count of execution ticks (instruction or p-code steps) for a thread key; a negative count is meaningless. All concrete step types inherit this guard.","triggerScenarios":"Constructing a step (e.g. TickStep/ExecutorStep) via its constructor or parse path with a negative tick count; arithmetic that subtracts past zero before building a step.","commonSituations":"Schedule parsing/computation that underflows; rewinding and re-deriving a step count without clamping; tests building steps with arbitrary ints.","solutions":["Pass a non-negative tick count; clamp computed counts with Math.max(0, n).","When splitting/merging schedules, recompute counts from absolute positions rather than differences that can go negative.","Use TraceSchedule's higher-level combine/rewind APIs which keep counts non-negative."],"exampleFix":"// before\nStep s = new TickStep(threadKey, remaining /* -3 */);\n\n// after\nStep s = new TickStep(threadKey, Math.max(0, remaining));","handlingStrategy":"validation","validationCode":"long ticks = Math.max(0, computedTicks);\nStep s = new TickStep(threadKey, ticks);","typeGuard":"static boolean validTickCount(long t) { return t >= 0; }","tryCatchPattern":null,"preventionTips":["Clamp derived step counts to >= 0 before constructing steps.","Prefer TraceSchedule's higher-level APIs which keep counts non-negative.","Recompute split counts from absolute positions, not signed deltas."],"tags":["ghidra","trace-modeling","schedule","step","illegal-argument"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}