clojure/clojure · error · RuntimeException

Too few arguments to throw, throw expects a single…

Error message

Too few arguments to throw, throw expects a single Throwable instance

What it means

The `throw` special form takes exactly one argument: a Throwable. The compiler's ThrowExpr.Parser throws this when a `(throw)` form has no arguments at all (count == 1, just the symbol). In eval context the form is wrapped in a generated fn, but arity of the throw form itself is still validated first at compile time.

Solutions

  1. Supply a Throwable expression: `(throw (ex-info "msg" {:k v}))` or `(throw (Exception. "msg"))`
  2. Fix the macro so it always produces exactly one throwable argument
  3. If failure may not occur, guard the throw: `(when bad (throw (ex-info ...)))`

Example fix

;; before
(throw)
;; after
(throw (ex-info "something went wrong" {:context :bad-input}))
Defensive patterns

Strategy: validation

Validate before calling

(defn safe-throw-check [form]
  (when (and (seq? form) (= 'throw (first form)))
    (when (< (count form) 2)
      (throw (ex-info "throw needs one Throwable" {:form form})))))

Prevention

When it happens

Trigger: Compiling `(throw)` with zero arguments; macro expansion that drops the exception expression leaving a bare `(throw)`.

Common situations: Macros that conditionally build `(throw ...)` and emit the empty form when a value is nil; hand-written code where the exception expression was deleted; typo leaving `(throw)` as a placeholder.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at src/jvm/clojure/lang/Compiler.java:2977

	}


	public Object eval() {
		throw Util.runtimeException("Can't eval throw");
	}

	public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
		excExpr.emit(C.EXPRESSION, objx, gen);
		gen.checkCast(THROWABLE_TYPE);
		gen.throwException();
	}

	static class Parser implements IParser{
		public Expr parse(C context, Object form) {
			if(context == C.EVAL)
				return analyze(context, RT.list(RT.list(FNONCE, PersistentVector.EMPTY, form)));
			else if(RT.count(form) == 1)
				throw Util.runtimeException("Too few arguments to throw, throw expects a single Throwable instance");
			else if(RT.count(form) > 2)
				throw Util.runtimeException("Too many arguments to throw, throw expects a single Throwable instance");
			return new ThrowExpr(analyze(C.EXPRESSION, RT.second(form)));
		}
	}
}


static public boolean subsumes(Class[] c1, Class[] c2){
	//presumes matching lengths
	Boolean better = false;
	for(int i = 0; i < c1.length; i++)
		{
		if(c1[i] != c2[i])// || c2[i].isPrimitive() && c1[i] == Object.class))
			{
			if(!c1[i].isPrimitive() && c2[i].isPrimitive()
			   //|| Number.class.isAssignableFrom(c1[i]) && c2[i].isPrimitive()
			   ||

View on GitHub (pinned to f3b143341d)