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
- Check (seq v) or (not (empty? v)) before pop
- Use (peek v) to test/inspect without removing
- Return EMPTY ([]) explicitly when the vector is empty instead of popping
- 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
- Check (seq v) before pop
- Use peek to inspect the top without removing
- Audit push/pop pairing in stack-style algorithms
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
- Can't pop empty list
- Invalid reference state
- NoSuchElementException
- NoSuchElementException
- NoSuchElementException
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)