clojure/clojure · error · IllegalArgumentException
Unexpected switch type
Error message
Unexpected switch type: ${switchType} What it means
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.
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.
Example fix
// before (defmacro case2 [& body] `(case* ~@body ... :switch-type :weird ...)) // after (defmacro case2 [& body] `(case* ~@body ... :switch-type :sparse ...))
Defensive patterns
Strategy: try-catch
Try / catch
(try
(case x :a 1 :b 2)
(catch IllegalArgumentException e
(if (re-find #"Unexpected switch type" (.getMessage e))
(do (println "broken case macro / mismatched clojure jars")
(fallback-dispatch x))
(throw e)))) Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Can't eval letfns
- Unexpected test type
- ArityException
- Bad binding form, expected matched symbol expression pairs
- Bad binding form, expected symbol, got:
AI-assisted analysis of clojure/clojure@f3b143341d (2026-09-09).
Data as JSON: /api/errors/ffff53c86df87a15.
Report an issue: GitHub.
Appendix: source
Thrown at src/jvm/clojure/lang/Compiler.java:9392
final static Keyword sparseKey = Keyword.intern(null, "sparse");
final static Keyword hashIdentityKey = Keyword.intern(null, "hash-identity");
final static Keyword hashEquivKey = Keyword.intern(null, "hash-equiv");
final static Keyword intKey = Keyword.intern(null, "int");
//(case* expr shift mask default map<minhash, [test then]> table-type test-type skip-check?)
public CaseExpr(int line, int column, LocalBindingExpr expr, int shift, int mask, int low, int high, Expr defaultExpr,
SortedMap<Integer,Expr> tests,HashMap<Integer,Expr> thens, Keyword switchType, Keyword testType, Set<Integer> skipCheck){
this.expr = expr;
this.shift = shift;
this.mask = mask;
this.low = low;
this.high = high;
this.defaultExpr = defaultExpr;
this.tests = tests;
this.thens = thens;
this.line = line;
this.column = column;
if (switchType != compactKey && switchType != sparseKey)
throw new IllegalArgumentException("Unexpected switch type: "+switchType);
this.switchType = switchType;
if (testType != intKey && testType != hashEquivKey && testType != hashIdentityKey)
throw new IllegalArgumentException("Unexpected test type: "+switchType);
this.testType = testType;
this.skipCheck = skipCheck;
Collection<Expr> returns = new ArrayList(thens.values());
returns.add(defaultExpr);
this.returnType = maybeJavaClass(returns);
if(RT.count(skipCheck) > 0 && RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))
{
RT.errPrintWriter()
.format("Performance warning, %s:%d:%d - hash collision of some case test constants; if selected, those entries will be tested sequentially.\n",
SOURCE_PATH.deref(), line, column);
}
}
public boolean hasJavaClass(){
return returnType != null;View on GitHub (pinned to f3b143341d)