{"record":{"id":"3f674d0576ce1804","repo":"clojure/clojure","slug":"first-argument-to-def-must-be-a-symbol","errorCode":null,"errorMessage":"First argument to def must be a Symbol","messagePattern":"First argument to def must be a Symbol","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/jvm/clojure/lang/Compiler.java","lineNumber":539,"sourceCode":"\n\tpublic Class getJavaClass(){\n\t\treturn Var.class;\n\t}\n\n\tstatic class Parser implements IParser{\n\t\tpublic Expr parse(C context, Object form) {\n\t\t\t//(def x) or (def x initexpr) or (def x \"docstring\" initexpr)\n\t\t\tString docstring = null;\n\t\t\tif(RT.count(form) == 4 && (RT.third(form) instanceof String)) {\n\t\t\t\tdocstring = (String) RT.third(form);\n\t\t\t\tform = RT.list(RT.first(form), RT.second(form), RT.fourth(form));\n\t\t\t}\n\t\t\tif(RT.count(form) > 3)\n\t\t\t\tthrow Util.runtimeException(\"Too many arguments to def\");\n\t\t\telse if(RT.count(form) < 2)\n\t\t\t\tthrow Util.runtimeException(\"Too few arguments to def\");\n\t\t\telse if(!(RT.second(form) instanceof Symbol))\n\t\t\t\t\tthrow Util.runtimeException(\"First argument to def must be a Symbol\");\n\t\t\tSymbol sym = (Symbol) RT.second(form);\n\t\t\tVar v = lookupVar(sym, true);\n\t\t\tif(v == null)\n\t\t\t\tthrow Util.runtimeException(\"Can't refer to qualified var that doesn't exist\");\n\t\t\tif(!v.ns.equals(currentNS()))\n\t\t\t\t{\n\t\t\t\tif(sym.ns == null)\n\t\t\t\t\t{\n\t\t\t\t\tv = currentNS().intern(sym);\n\t\t\t\t\tregisterVar(v);\n\t\t\t\t\t}\n//\t\t\t\t\tthrow Util.runtimeException(\"Name conflict, can't def \" + sym + \" because namespace: \" + currentNS().name +\n//\t\t\t\t\t                    \" refers to:\" + v);\n\t\t\t\telse\n\t\t\t\t\tthrow Util.runtimeException(\"Can't create defs outside of current ns\");\n\t\t\t\t}\n\t\t\tIPersistentMap mm = sym.meta();\n\t\t\tboolean isDynamic = RT.booleanCast(RT.get(mm,dynamicKey));","sourceCodeStart":521,"sourceCodeEnd":557,"githubUrl":"https://github.com/clojure/clojure/blob/f3b143341d6efc6428b523b2eaa099a6cc99156e/src/jvm/clojure/lang/Compiler.java#L521-L557","documentation":"The second element of a def form is the name being interned and must be a Symbol — that is what the compiler interns into the current namespace as a Var. If it is any other type (string, keyword, collection), the compiler cannot create the var and throws immediately.","triggerScenarios":"(def \"x\" 1), (def :x 1), (def [a b] coll), or a macro expansion where the name position received a non-symbol value such as a resolved value or nil-wrapped form.","commonSituations":"Macros that pass the value instead of the (quoted) name: (def ~name ...) where name was already evaluated to a string; destructuring attempts inside def; dynamic name construction done with strings instead of (symbol ...).","solutions":["Use a bare symbol as the name: (def x 1).","In macros, ensure the name is a symbol: (def ~(symbol name-str) value) or pass 'x quoted.","To bind a collection, use destructuring in let/loop, not def."],"exampleFix":"// before\n(def \"my-var\" 42)\n// after\n(def my-var 42)","handlingStrategy":"type-guard","validationCode":"(when-not (symbol? name)\n  (throw (ex-info \"def name must be a symbol\" {:name name})))","typeGuard":"(defn valid-def-name? [x] (symbol? x))","tryCatchPattern":"try {\n  (eval `(def ~name ~value))\n} catch (RuntimeException e) {\n  (when (.contains (.getMessage e) \"must be a Symbol\")\n    (println \"Name position got:\" (pr-str name)))\n}","preventionTips":["Quote the name in macros: pass 'x, not x.","Convert runtime strings with (symbol s) before building def forms.","Use let destructuring for collections, never def."],"tags":["compiler","def","clojure","symbols"],"backgroundTag":"invalid-identifier-format","analyzedSha":"f3b143341d6efc6428b523b2eaa099a6cc99156e","analyzedAt":"2026-09-09T12:04:58.961Z","contentChangedAt":"2026-09-09T12:04:58.961Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}