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
- Remove the extra arguments so the form is (def name value) or (def name "doc" value).
- If metadata was intended, attach it with ^meta reader syntax or (def ^{:k v} name value) instead of positional arguments.
- 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
- Keep def forms to (def name value) or (def name "doc" value).
- Attach metadata with ^ reader syntax, not extra positional arguments.
- Macroexpand generated defs before evaluating them.
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
- Too few arguments to def
- ArityException
- Can't have 2 overloads with same arity
- First argument to def must be a Symbol
- fns taking primitives support only 4 or fewer args
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);
elseView on GitHub (pinned to f3b143341d)