clojure/clojure · error · IllegalStateException

Can't pop empty vector

Error message

Can't pop empty vector

What it means

pop() on a PersistentVector with zero elements throws IllegalStateException("Can't pop empty vector"). Popping an empty vector has no meaningful persistent value, so Clojure raises instead of returning EMPTY.

Solutions

  1. Check (seq v) or (not (empty? v)) before pop
  2. Use (peek v) to test/inspect without removing
  3. Return EMPTY ([]) explicitly when the vector is empty instead of popping
  4. Fix the push/pop balance in the algorithm

Example fix

// before
(def v' (pop v))
// after
(def v' (if (seq v) (pop v) v))
Defensive patterns

Strategy: validation

Validate before calling

// clojure
(defn pop-safe [v] (if (seq v) (pop v) v))

Type guard

(defn poppable? [v] (and (vector? v) (seq v)))

Try / catch

(try (pop v)
  (catch IllegalStateException _ []))

Prevention

When it happens

Trigger: (pop []) or .pop() when count is 0 — typically popping in a loop without checking emptiness, or a stack-like algorithm that pops more than it pushed.

Common situations: Stack algorithms (DFS, balanced-bracket parsers) where pops outnumber pushes, reducing a vector with pop until empty then one pop too many, mis-sequenced conj/pop pairs.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of clojure/clojure@f3b143341d (2026-09-09). Data as JSON: /api/errors/8cad00f66b12fc8b. Report an issue: GitHub.

Appendix: source

Thrown at src/jvm/clojure/lang/PersistentVector.java:620

//		else
//			newchild = expansion.val;
//		}
//	//expansion
//	if(arr.length == 32)
//		{
//		expansion.val = new Object[]{newchild};
//		return arr;
//		}
//	Object[] ret = new Object[arr.length + 1];
//	System.arraycopy(arr, 0, ret, 0, arr.length);
//	ret[arr.length] = newchild;
//	expansion.val = null;
//	return ret;
//}

public PersistentVector pop(){
	if(cnt == 0)
		throw new IllegalStateException("Can't pop empty vector");
	if(cnt == 1)
		return EMPTY.withMeta(meta());
	//if(tail.length > 1)
	if(cnt-tailoff() > 1)
		{
		Object[] newTail = new Object[tail.length - 1];
		System.arraycopy(tail, 0, newTail, 0, newTail.length);
		return new PersistentVector(meta(), cnt - 1, shift, root, newTail);
		}
	Object[] newtail = arrayFor(cnt - 2);

	Node newroot = popTail(shift, root);
	int newshift = shift;
	if(newroot == null)
		{
		newroot = EMPTY_NODE;
		}
	if(shift > 5 && newroot.array[1] == null)

View on GitHub (pinned to f3b143341d)