{"record":{"id":"ffff53c86df87a15","repo":"clojure/clojure","slug":"unexpected-switch-type-switchtype","errorCode":null,"errorMessage":"Unexpected switch type: ${switchType}","messagePattern":"Unexpected switch type: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/jvm/clojure/lang/Compiler.java","lineNumber":9392,"sourceCode":"    final static Keyword sparseKey = Keyword.intern(null, \"sparse\");\n    final static Keyword hashIdentityKey = Keyword.intern(null, \"hash-identity\");\n    final static Keyword hashEquivKey = Keyword.intern(null, \"hash-equiv\");\n    final static Keyword intKey = Keyword.intern(null, \"int\");\n\t//(case* expr shift mask default map<minhash, [test then]> table-type test-type skip-check?)\n\tpublic CaseExpr(int line, int column, LocalBindingExpr expr, int shift, int mask, int low, int high, Expr defaultExpr,\n\t        SortedMap<Integer,Expr> tests,HashMap<Integer,Expr> thens, Keyword switchType, Keyword testType, Set<Integer> skipCheck){\n\t\tthis.expr = expr;\n\t\tthis.shift = shift;\n\t\tthis.mask = mask;\n\t\tthis.low = low;\n\t\tthis.high = high;\n\t\tthis.defaultExpr = defaultExpr;\n\t\tthis.tests = tests;\n\t\tthis.thens = thens;\n\t\tthis.line = line;\n\t\tthis.column = column;\n\t\tif (switchType != compactKey && switchType != sparseKey)\n\t\t    throw new IllegalArgumentException(\"Unexpected switch type: \"+switchType);\n\t\tthis.switchType = switchType;\n        if (testType != intKey && testType != hashEquivKey && testType != hashIdentityKey)\n            throw new IllegalArgumentException(\"Unexpected test type: \"+switchType);\n\t\tthis.testType = testType;\n\t\tthis.skipCheck = skipCheck;\n\t\tCollection<Expr> returns = new ArrayList(thens.values());\n\t\treturns.add(defaultExpr);\n\t\tthis.returnType = maybeJavaClass(returns);\n        if(RT.count(skipCheck) > 0 && RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))\n            {\n            RT.errPrintWriter()\n              .format(\"Performance warning, %s:%d:%d - hash collision of some case test constants; if selected, those entries will be tested sequentially.\\n\",\n                      SOURCE_PATH.deref(), line, column);\n            }\n\t}\n\n\tpublic boolean hasJavaClass(){\n\t    return returnType != null;","sourceCodeStart":9374,"sourceCodeEnd":9410,"githubUrl":"https://github.com/clojure/clojure/blob/f3b143341d6efc6428b523b2eaa099a6cc99156e/src/jvm/clojure/lang/Compiler.java#L9374-L9410","documentation":"The SwitchExpr constructor validates that switchType is one of the two known constants (compactKey or sparseKey) generated by the case* macroexpansion. Receiving any other value means the internal contract between the case macro and the compiler expression node is broken, so an IllegalArgumentException is thrown.","triggerScenarios":"case*/switch* macroexpansion emitting a :switch-type other than :compact or :sparse, e.g. from a broken/patched core macro or macro overrides that shadow clojure.core/case with a buggy implementation.","commonSituations":"Using a library or custom macro that redefines case or case*; bytecode/compiler version mismatch (a newer clojure.jar with older core.clj on the classpath or vice versa); experimental branch code.","solutions":["Check the classpath for duplicate/mismatched clojure jars (mvn dependency:tree) and pin a single consistent Clojure version.","Verify no local macro shadows clojure.core/case or redefines case*; use fully-qualified clojure.core/case if needed.","If you wrote a custom switch emitter, pass only :compact or :sparse as :switch-type."],"exampleFix":"// before\n(defmacro case2 [& body] `(case* ~@body ... :switch-type :weird ...))\n// after\n(defmacro case2 [& body] `(case* ~@body ... :switch-type :sparse ...))","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"(try\n  (case x :a 1 :b 2)\n  (catch IllegalArgumentException e\n    (if (re-find #\"Unexpected switch type\" (.getMessage e))\n      (do (println \"broken case macro / mismatched clojure jars\")\n          (fallback-dispatch x))\n      (throw e))))","preventionTips":["Avoid macros that shadow or reimplement clojure.core/case or case*.","Ensure exactly one clojure jar version on the classpath (mvn dependency:tree, lein deps :tree).","After compiler patches, recompile core.clj consistently with the JVM sources."],"tags":["clojure","compiler","case","internal"],"backgroundTag":"invalid-enum-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"}