clojure/clojure · error · RuntimeException

Too many arguments to def

Error message

Too many arguments to def

What it means

During macroexpansion of a def special form, the compiler accepts at most (def sym init) or (def sym "docstring" init). If the form still has more than 3 elements after the docstring case is peeled off, the def is malformed and the compiler throws instead of guessing which extra argument was intended.

Solutions

  1. Remove the extra arguments so the form is (def name value) or (def name "doc" value).
  2. If metadata was intended, attach it with ^meta reader syntax or (def ^{:k v} name value) instead of positional arguments.
  3. Inspect the macro that emits the def and fix its expansion (macroexpand-1 the call).

Example fix

// before
(def config "app config" {:a 1} :extra)
// after
(def ^{:doc "app config"} config {:a 1})
Defensive patterns

Strategy: validation

Validate before calling

(when (> (count form) (if (string? (nth form 2 nil)) 4 3))
  (throw (ex-info "def form has too many arguments" {:form form})))

Try / catch

try {
  (eval form)
} catch (RuntimeException e) {
  (when (.contains (.getMessage e) "Too many arguments to def")
    (println "Fix def form arity:" form))
}

Prevention

When it happens

Trigger: Evaluating a def form with extra elements, e.g. (def x 1 2), (def x 1 {:meta 1} 2), or a mis-built def generated by a macro that concatenates one argument too many.

Common situations: Hand-written defs with leftover arguments; macros that splice collections into def without flattening; copy-paste from languages allowing multiple bindings in one declaration; refactoring that left a stale argument in place.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

	public boolean hasJavaClass(){
		return true;
	}

	public Class getJavaClass(){
		return Var.class;
	}

	static class Parser implements IParser{
		public Expr parse(C context, Object form) {
			//(def x) or (def x initexpr) or (def x "docstring" initexpr)
			String docstring = null;
			if(RT.count(form) == 4 && (RT.third(form) instanceof String)) {
				docstring = (String) RT.third(form);
				form = RT.list(RT.first(form), RT.second(form), RT.fourth(form));
			}
			if(RT.count(form) > 3)
				throw Util.runtimeException("Too many arguments to def");
			else if(RT.count(form) < 2)
				throw Util.runtimeException("Too few arguments to def");
			else if(!(RT.second(form) instanceof Symbol))
					throw Util.runtimeException("First argument to def must be a Symbol");
			Symbol sym = (Symbol) RT.second(form);
			Var v = lookupVar(sym, true);
			if(v == null)
				throw Util.runtimeException("Can't refer to qualified var that doesn't exist");
			if(!v.ns.equals(currentNS()))
				{
				if(sym.ns == null)
					{
					v = currentNS().intern(sym);
					registerVar(v);
					}
//					throw Util.runtimeException("Name conflict, can't def " + sym + " because namespace: " + currentNS().name +
//					                    " refers to:" + v);
				else

View on GitHub (pinned to f3b143341d)