{"record":{"id":"1aae2e2daf80114b","repo":"clojure/clojure","slug":"too-few-arguments-to-throw-throw-expects-a-single","errorCode":null,"errorMessage":"Too few arguments to throw, throw expects a single Throwable instance","messagePattern":"Too few arguments to throw, throw expects a single Throwable instance","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/jvm/clojure/lang/Compiler.java","lineNumber":2977,"sourceCode":"\t}\n\n\n\tpublic Object eval() {\n\t\tthrow Util.runtimeException(\"Can't eval throw\");\n\t}\n\n\tpublic void emit(C context, ObjExpr objx, GeneratorAdapter gen){\n\t\texcExpr.emit(C.EXPRESSION, objx, gen);\n\t\tgen.checkCast(THROWABLE_TYPE);\n\t\tgen.throwException();\n\t}\n\n\tstatic class Parser implements IParser{\n\t\tpublic Expr parse(C context, Object form) {\n\t\t\tif(context == C.EVAL)\n\t\t\t\treturn analyze(context, RT.list(RT.list(FNONCE, PersistentVector.EMPTY, form)));\n\t\t\telse if(RT.count(form) == 1)\n\t\t\t\tthrow Util.runtimeException(\"Too few arguments to throw, throw expects a single Throwable instance\");\n\t\t\telse if(RT.count(form) > 2)\n\t\t\t\tthrow Util.runtimeException(\"Too many arguments to throw, throw expects a single Throwable instance\");\n\t\t\treturn new ThrowExpr(analyze(C.EXPRESSION, RT.second(form)));\n\t\t}\n\t}\n}\n\n\nstatic public boolean subsumes(Class[] c1, Class[] c2){\n\t//presumes matching lengths\n\tBoolean better = false;\n\tfor(int i = 0; i < c1.length; i++)\n\t\t{\n\t\tif(c1[i] != c2[i])// || c2[i].isPrimitive() && c1[i] == Object.class))\n\t\t\t{\n\t\t\tif(!c1[i].isPrimitive() && c2[i].isPrimitive()\n\t\t\t   //|| Number.class.isAssignableFrom(c1[i]) && c2[i].isPrimitive()\n\t\t\t   ||","sourceCodeStart":2959,"sourceCodeEnd":2995,"githubUrl":"https://github.com/clojure/clojure/blob/f3b143341d6efc6428b523b2eaa099a6cc99156e/src/jvm/clojure/lang/Compiler.java#L2959-L2995","documentation":"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.","triggerScenarios":"Compiling `(throw)` with zero arguments; macro expansion that drops the exception expression leaving a bare `(throw)`.","commonSituations":"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.","solutions":["Supply a Throwable expression: `(throw (ex-info \"msg\" {:k v}))` or `(throw (Exception. \"msg\"))`","Fix the macro so it always produces exactly one throwable argument","If failure may not occur, guard the throw: `(when bad (throw (ex-info ...)))`"],"exampleFix":";; before\n(throw)\n;; after\n(throw (ex-info \"something went wrong\" {:context :bad-input}))","handlingStrategy":"validation","validationCode":"(defn safe-throw-check [form]\n  (when (and (seq? form) (= 'throw (first form)))\n    (when (< (count form) 2)\n      (throw (ex-info \"throw needs one Throwable\" {:form form})))))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass exactly one exception expression to throw","Verify macro expansions with macroexpand before compiling","Use (when cond (throw ...)) instead of a bare throw placeholder"],"tags":["clojure","compiler","throw","arity"],"backgroundTag":"missing-required-argument","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"}