NationalSecurityAgency/ghidra · error · IllegalArgumentException

Thread must be given, e.g., 0:t1-3, since the last thread or

Error message

Thread must be given, e.g., 0:t1-3, since the last thread or snapshot event thread is not given.

What it means

Step.requireThread throws this specific message when the thread resolved to null AND the key is -1 (the sentinel for 'last thread or event thread'). This means the caller asked to operate on the event thread, but no event thread is available in the current context — the trace has no snapshot event thread and no last-thread state to fall back on.

Source

Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/Step.java:112

	StepType getType();

	default int getTypeOrder() {
		return getType().ordinal();
	}

	boolean isNop();

	long getThreadKey();

	default boolean isEventThread() {
		return getThreadKey() == -1;
	}

	static TraceThread requireThread(TraceThread thread, long key) {
		if (thread == null) {
			if (key == -1) {
				throw new IllegalArgumentException("Thread must be given, e.g., 0:t1-3, " +
					"since the last thread or snapshot event thread is not given.");
			}
			throw new IllegalArgumentException(
				"Thread with key %d does not exist in given trace".formatted(key));
		}
		return thread;
	}

	default TraceThread getThread(TraceThreadManager tm, TraceThread eventThread) {
		long key = getThreadKey();
		return requireThread(isEventThread() ? eventThread : tm.getThread(key), key);
	}

	long getTickCount();

	long getSkipCount();

	long getPatchCount();

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Specify the thread explicitly in the schedule: '0:t1-5' instead of '0:5'
  2. Ensure the trace has an event thread set before using implicit-thread schedules: check trace.getThreadManager().getAllThreads() is non-empty
  3. If building schedules programmatically, use a concrete thread key obtained from the trace rather than -1
  4. Verify the snapshot has an event thread: snapshot.getEventThread() != null before stepping

Example fix

// before
// schedule uses implicit event thread: "snap:5"
TraceSchedule.parse("0:5", Source.ABNORMAL, TimeRadix.DEC);
// after
// specify thread explicitly: "snap:t1-5"
TraceSchedule.parse("0:t1-5", Source.ABNORMAL, TimeRadix.DEC);
Defensive patterns

Strategy: validation

Validate before calling

boolean hasEventThread(Trace trace, TraceSnapshot snap) {
    return snap != null && snap.getEventThread() != null
        || !trace.getThreadManager().getAllThreads().isEmpty();
}

Type guard

// N/A — runtime context check

Try / catch

try {
    TraceThread thread = step.getThread(tm, eventThread);
} catch (IllegalArgumentException e) {
    // no event thread available; require explicit thread key in schedule
}

Prevention

When it happens

Trigger: Calling step.getThread(threadManager, null) when the step uses key -1 (event thread) but eventThread is null. This happens when a schedule references the implicit event thread but the trace or snapshot has no associated event thread. Also when operating on a freshly created trace with no threads or events recorded yet.

Common situations: Creating a schedule with a default thread reference (no 'tN-' prefix) and applying it to a trace that has no threads or no snapshot event thread. Loading a trace from a target session where the event thread was never set. Using schedules from one trace context on a different trace where thread keys differ.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/f7bc877bb9ed071e. Report an issue: GitHub.