NationalSecurityAgency/ghidra · error · IllegalArgumentException

max < min: min={min},max={max}

Error message

max < min: min={min},max={max}

What it means

Thrown by Lifespan.Domain.closed(long min, long max): a lifespan is an inclusive snapshot-key range [min,max], so max < min is an empty/invalid span. Ghidra treats the minimum snapshot key as the lower bound, so an inverted range is a programming error rather than an empty-range request.

Source

Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/Lifespan.java:143

			return EMPTY;
		}
		return DOMAIN.atMost(DOMAIN.dec(snap));
	}

	/**
	 * The domain of snapshot keys
	 */
	public enum Domain implements Span.Domain<Long, Lifespan> {
		INSTANCE;

		@Override
		public Lifespan closed(Long min, Long max) {
			return closed(min.longValue(), max.longValue());
		}

		public Lifespan closed(long min, long max) {
			if (max < min) {
				throw new IllegalArgumentException("max < min: min=" + min + ",max=" + max);
			}
			return new Impl(min, max);
		}

		@Override
		public Lifespan newSpan(Long min, Long max) {
			return new Impl(min, max);
		}

		public Lifespan value(long n) {
			return new Impl(n, n);
		}

		@Override
		public Lifespan atMost(Long max) {
			return atMost(max.longValue());
		}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Order the bounds before constructing: long lo = Math.min(a, b), hi = Math.max(a, b); then Lifespan.closed(lo, hi).
  2. Verify the caller's snapshot keys are in ascending order.
  3. If an empty result is intended, handle that case explicitly rather than passing an inverted range.
  4. Add an assertion/unit test on the span constructor inputs.

Example fix

// before
Lifespan span = Lifespan.span(fromSnap, toSnap); // toSnap < fromSnap

// after
long lo = Math.min(fromSnap, toSnap);
long hi = Math.max(fromSnap, toSnap);
Lifespan span = Lifespan.span(lo, hi);
Defensive patterns

Strategy: validation

Validate before calling

long lo = Math.min(a, b), hi = Math.max(a, b);
Lifespan span = Lifespan.span(lo, hi);

Type guard

static boolean validSpan(long min, long max) { return max >= min; }

Prevention

When it happens

Trigger: Constructing a Lifespan via Domain.INSTANCE.closed(min, max), Lifespan.closed(...), or any code path that builds a span from two keys where the 'max' key is smaller than the 'min' key (e.g. interchanged arguments, or a computed end that came before the start).

Common situations: Swapping min/max arguments; computing max from a sub-snapshot's parent where ordering is inverted; passing user-supplied from/to snapshot indices without ordering; off-by-one in span arithmetic.

Related errors


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