{"record":{"id":"87e19d96f7c5ab49","repo":"clojure/clojure","slug":"bad-binding-form-expected-symbol-got","errorCode":null,"errorMessage":"Bad binding form, expected symbol, got: ","messagePattern":"Bad binding form, expected symbol, got: ","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/jvm/clojure/lang/Compiler.java","lineNumber":2834,"sourceCode":"\t\t\t\t\tbody = body.cons(f);\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tif(bodyExpr == null)\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tVar.pushThreadBindings(RT.map(NO_RECUR, true, METHOD_RETURN_CONTEXT, null));\n\t\t\t\t\t\t\tbodyExpr = (new BodyExpr.Parser()).parse(context, RT.seq(body));\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tVar.popThreadBindings();\n\t\t\t\t\t\t}\n\n\t\t\t\t\tif(Util.equals(op, CATCH))\n\t\t\t\t\t\t{\n\t\t\t\t\t\tClass c = HostExpr.maybeClass(RT.second(f), false);\n\t\t\t\t\t\tif(c == null)\n\t\t\t\t\t\t\tthrow new IllegalArgumentException(\"Unable to resolve classname: \" + RT.second(f));\n\t\t\t\t\t\tif(!(RT.third(f) instanceof Symbol))\n\t\t\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\t\t\t\"Bad binding form, expected symbol, got: \" + RT.third(f));\n\t\t\t\t\t\tSymbol sym = (Symbol) RT.third(f);\n\t\t\t\t\t\tif(sym.getNamespace() != null)\n\t\t\t\t\t\t\tthrow Util.runtimeException(\"Can't bind qualified name:\" + sym);\n\n\t\t\t\t\t\tIPersistentMap dynamicBindings = RT.map(LOCAL_ENV, LOCAL_ENV.deref(),\n\t\t\t\t\t\t                                        NEXT_LOCAL_NUM, NEXT_LOCAL_NUM.deref(),\n\t\t\t\t\t\t                                        IN_CATCH_FINALLY, RT.T);\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tVar.pushThreadBindings(dynamicBindings);\n\t\t\t\t\t\t\tLocalBinding lb = registerLocal(sym,\n\t\t\t\t\t\t\t                                (Symbol) (RT.second(f) instanceof Symbol ? RT.second(f)\n\t\t\t\t\t\t\t                                                                         : null),\n\t\t\t\t\t\t\t                                null,false);\n\t\t\t\t\t\t\tExpr handler = (new BodyExpr.Parser()).parse(C.EXPRESSION, RT.next(RT.next(RT.next(f))));\n\t\t\t\t\t\t\tcatches = catches.cons(new CatchClause(c, lb, handler));\n\t\t\t\t\t\t\t}","sourceCodeStart":2816,"sourceCodeEnd":2852,"githubUrl":"https://github.com/clojure/clojure/blob/f3b143341d6efc6428b523b2eaa099a6cc99156e/src/jvm/clojure/lang/Compiler.java#L2816-L2852","documentation":"Sentinel validation in the catch clause parser: the binding position (third element of the catch form) must be a Symbol to receive the caught exception, but another form (string, keyword, vector, etc.) was supplied. At-fault input: a non-symbol binding, e.g. (catch Exception \"e\" ...).","triggerScenarios":"(catch Exception \"e\" ...), (catch Exception [e] ...), or (catch Exception a/b ...) with a namespace-qualified symbol as the binding name.","commonSituations":"Copy-paste errors in catch clauses; macro-generated catch with a form instead of a symbol; accidentally using destructuring directly in catch (not supported directly).","solutions":["Make the catch binding a simple unqualified symbol: (catch Exception e ...)","If you want destructuring, bind a symbol then destructure inside the body","Check macro-generated code emits a plain symbol"],"exampleFix":";; before\n(catch Exception {:keys [message]} ...)\n;; after\n(catch Exception e (let [{:keys [message]} (ex-data e)] ...))","handlingStrategy":"validation","validationCode":"(defn valid-catch? [clause]\n  (and (seq? clause)\n       (= 'catch (first clause))\n       (symbol? (nth clause 2 nil))\n       (nil? (namespace (nth clause 2 nil)))))","typeGuard":null,"tryCatchPattern":"(try (eval clause)\n  (catch IllegalArgumentException e\n    (when (.startsWith (.getMessage e) \"Bad binding form\")\n      (println \"catch binding must be a plain symbol\"))))","preventionTips":["Always bind catch to a simple unqualified symbol","Destructure inside the catch body, not in the binding","Review macro-generated catch clauses for non-symbol bindings"],"tags":["clojure","compiler","exception-handling","syntax"],"backgroundTag":"invalid-argument-value","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"}