{"record":{"id":"7df6593016201cbf","repo":"NationalSecurityAgency/ghidra","slug":"cannot-rewind-a-negative-number","errorCode":null,"errorMessage":"Cannot rewind a negative number","messagePattern":"Cannot rewind 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":98,"sourceCode":"\t * Add to the count of this step\n\t * \n\t * @param steps the count to add\n\t */\n\tpublic void advance(long steps) {\n\t\tif (steps < 0) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot advance a negative number\");\n\t\t}\n\t\tlong newCount = tickCount + steps;\n\t\tif (newCount < 0) {\n\t\t\tthrow new IllegalArgumentException(\"Total step count exceeds LONG_MAX\");\n\t\t}\n\t\tthis.tickCount = newCount;\n\t}\n\n\t@Override\n\tpublic long rewind(long steps) {\n\t\tif (steps < 0) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot rewind a negative number\");\n\t\t}\n\t\tlong diff = this.tickCount - steps;\n\t\tthis.tickCount = Long.max(0, diff);\n\t\treturn -diff;\n\t}\n\n\t@Override\n\tpublic boolean isCompatible(Step step) {\n\t\tif (!(step.getClass() == this.getClass())) {\n\t\t\treturn false;\n\t\t}\n\t\tAbstractStep as = (AbstractStep) step;\n\t\treturn this.threadKey == as.threadKey || as.threadKey == -1;\n\t}\n\n\t@Override\n\tpublic void addTo(Step step) {\n\t\tassert isCompatible(step);","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/AbstractStep.java#L80-L116","documentation":"Thrown by AbstractStep.rewind(long steps) when steps < 0. rewind() only reduces a step's tick count (clamped at 0), so a negative argument is rejected; use advance() to grow the count.","triggerScenarios":"Calling step.rewind(n) with n < 0, e.g. passing a signed delta straight into rewind.","commonSituations":"Reusing a signed delta for both directions; schedule arithmetic where the delta's sign was not normalized.","solutions":["Route growth through advance(): if (steps >= 0) rewind(steps); else advance(-steps).","Guarantee the value passed to rewind is non-negative.","Use higher-level schedule APIs that pick advance vs rewind from the sign."],"exampleFix":"// before\nstep.rewind(delta); // delta < 0 -> exception\n\n// after\nif (delta >= 0) step.rewind(delta);\nelse step.advance(-delta);","handlingStrategy":"validation","validationCode":"if (delta >= 0) step.rewind(delta);\nelse step.advance(-delta);","typeGuard":"static boolean validRewind(long steps) { return steps >= 0; }","tryCatchPattern":null,"preventionTips":["Choose advance vs rewind from the sign of the delta.","Normalize deltas before calling schedule step APIs."],"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"}