NationalSecurityAgency/ghidra · error · ValueError
Schedule must be in form [snap]:[steps]. Got '{s}'
Error message
Schedule must be in form [snap]:[steps]. Got '{s}' What it means
Raised by Schedule.parse() when the input string contains more than one colon, i.e. it cannot be split into a [snap] or [snap]:[steps] pair. The Schedule dataclass represents a position in a trace as a snapshot id plus an optional step count. Note that non-numeric parts like 'abc' hit int() first and raise a different ValueError, so this specific message only fires on inputs with 3+ colon-separated parts.
Source
Thrown at Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py:157
Until we have need more capable schedules here, we'll just keep it
at this. TODO: We might need another flag to indicate the kind of
steps here. It seems in Microsoft TTD, it's the number of
instructions executed since the last event. However, in rr/gdb, it
seems it's the number of branch instructions encountered.
"""
snap: int
steps: int = 0
@staticmethod
def parse(s: str) -> 'Schedule':
parts = s.split(':')
if len(parts) == 1:
return Schedule(int(parts[0]))
elif len(parts) == 2:
return Schedule(int(parts[0]), int(parts[1]))
else:
raise ValueError(
f"Schedule must be in form [snap]:[steps]. Got '{s}'")
def __str__(self) -> str:
if self.steps == 0:
return f"{self.snap}"
return f"{self.snap}:{self.steps}"
@dataclass(frozen=True)
class DetachedObject:
id: int
path: str
@dataclass(frozen=True)
class TraceObject:
"""A proxy for a TraceObject."""
trace: 'Trace'View on GitHub (pinned to d5f144c24d)
Solutions
- Strip/normalize the input to a single optional colon before calling parse: pre-split on ':' and reject early if len != 1 or 2.
- Validate with a regex like ^\d+(:\d+)?$ before calling parse so the error never reaches the library.
- Wrap parse() in try/except ValueError and report the offending value back to the user rather than letting it surface raw.
Example fix
// before
sched = Schedule.parse(user_input)
// after
import re
if not re.fullmatch(r'\d+(:\d+)?', user_input.strip()):
raise ValueError(f'Expected [snap]:[steps], got {user_input!r}')
sched = Schedule.parse(user_input.strip()) Defensive patterns
Strategy: validation
Validate before calling
import re
assert isinstance(s, str)
if not re.fullmatch(r'\d+(:\d+)?', s.strip()):
raise ValueError(f'Bad schedule {s!r}; expected [snap]:[steps]') Type guard
def is_schedule_str(s) -> bool:
import re
return isinstance(s, str) and bool(re.fullmatch(r'\d+(:\d+)?', s.strip())) Try / catch
try:
sched = Schedule.parse(raw)
except ValueError:
# report to user, fall back, or re-raise with context
raise Prevention
- Validate schedule strings at the UI/config boundary.
- Always source schedules from a single normalized constant or parser.
When it happens
Trigger: Calling Schedule.parse('1:2:3'), Schedule.parse('a:b:c:d'), or passing a snapshot path/range string that contains multiple colons. Any caller that forwards unvalidated user or file-derived text into parse() reaches this branch.
Common situations: Pasting a schedule from a UI that formats it as 'snap:steps:extra', reading a malformed config/script argument, or a debugger front-end that passes a full timestamp or address-range string where a bare schedule is expected.
Related errors
- No saved offers to launch {}
- Range [%s:%x+%x] entirely exceeds space min
- Trace is not from this connection
- CreateTrace: path (name) cannot be empty
- snap or time required
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/978688027b9b3faa.
Report an issue: GitHub.