Expression switch exception naming

Brian Goetz brian.goetz at
Fri Mar 30 15:35:03 UTC 2018

I think we are the heart of the disagreement.  I do not think that 
"someone added an enum constant" is necessarily a classpath insanity 
thing.  Its just as likely to be a garden-variety "you made one 
assumption over here and another over there" within the same codebase.  
(And, we've told people for years that its OK to add enum constants.)

I think its at least as likely that this is in the same category as any 
other assumption we make about code we call.  Like "this method never 
returns null".  Or "this method says it returns Object, but I know it 
always returns String, so I'll cast to String."

So, it seems that the purpose of this exception is not to cast blame on 
the classpath, but to pinpoint the erroneous assumption. Maybe Y 
shouldn't have gotten new enum constants.  Maybe X made bad assumptions 
about the future maintenance trajectory of Y. Either way, X and Y have 
to get together and get their story straight.  So the exception should 
broker that meeting.  And its seems at least as likely as not that X and 
Y are the same maintainer.

If you got a stack trace that said:

     UnexpectedEnumValueException: surprising enum constant 
TrafficLight.BLUE; expected one of RED, YELLOW, GREEN
         at: MyClass.switchOnTrafficLightColors (line 666)


     UnexpectedSealedTypeMemberException: surprising subtype Blue of 
sealed type TrafficLightColors, expected one of Red, Yellow, Green

doesn't that meet your requirement?  You look at the exception, and it 
says that a value was found that violated an assumption in your code.  
It could either be the fault of the enum maintainer or of the switch 
maintainer (who might well be the same person.)

On 3/30/2018 11:09 AM, Kevin Bourrillion wrote:
> I think my overarching point is still this one:
>     "Today, an experienced developer knows that there is a category of
>     Errors that, when you see them in the absence of reflection,
>     always implicate this kind of classpath issue. I can't see why
>     this would not belong in that same category."
> The distinction, when a stack trace has just ruined my day, of whether 
> I need to start thinking hard about what /real/ mistake I might have 
> made /in my code, /or whether I probably just have Class Path Insanity 
> I should check out first, seems to be like a very high order 
> distinction - more useful to illuminate than other various 
> distinctions we can make.
> On Wed, Mar 28, 2018 at 12:48 PM, Brian Goetz <brian.goetz at 
> <mailto:brian.goetz at>> wrote:
>>     I have been figuring that if the client /has/ a reasonable way to
>>     handle unknown values then it will probably go ahead and do that
>>     (with a `default`).
>     I think that's a fair assumption for your codebase, but not in
>     general.  Developers will surely do this:
>         x = switch (trafficLight) {
>             case RED -> ...
>             case YELLOW -> ...
>             case GREEN -> ...
>         }
>     and leave out a default because they can.  So they get a default
>     default, one that throws.  No problem.
>     The only question here is: what to throw.  My argument is that
>     Error is just too strong an indicator.  (It's like using fatal as
>     your logging level for everything; it would be more useful to use
>     warning for things that aren't fatal).
>     From the Error doc:
>     An|Error|is a subclass of|Throwable|that indicates serious
>     problems that a reasonable application should not try to catch.
>     Most such errors are abnormal conditions.
>     Serious problems mean that underlying VM mechanism have failed. 
>     Encountering an unexpected input is not in this category.  Sure,
>     it deserves an exception, but its not an ICCE.
>>     Therefore I assumed that what we're talking about in this
>>     conversation is the/other/ kind, where there is nothing safe they
>>     can do - for example if I wrote a method that displays a time
>>     interval as "10 ns" or "20 s", I may not find it acceptable for
>>     me to start displaying "30 <unknown unit>" once I get handed
>>     TimeUnit.DAYS. My code is broken either way. If a constant is
>>     added, I need to react to that, just like I do with a new
>>     interface method. What does it really mean to say that this
>>     client "brings a piece of the responsibility" if it doesn't
>>     really have a choice?
>     It's not unlike this:
>         AnEnum e = f(...);
>         switch (e) {
>             ...
>         }
>     and not being prepared for a null.  You'll get an NPE. The local
>     code isn't expected to deal with it, but somewhere up the stack,
>     someone is prepared to deal with it, discard the offending
>     incoming work item, log what happened, and re-enter the work loop.
>>     So, I'm not quite yet following why the binary/source
>>     compatibility distinction, or the opt-in distinction, really
>>     makes all the difference here.
>     Some incompatibilities are more of a fire drill than others. 
>     Binary incompatibilities (e.g., removing a method) are harder to
>     recover from than unexpected inputs.  Further, while there may be
>     no good _local_ recover for an unexpected input, there often is a
>     reasonable global recovery.  Error means "fire drill".  I claim
>     this doesn't rise to the level of Error; it's more like
>     NumberFormatException or NPE or ClassCastException.
> -- 
> Kevin Bourrillion | Java Librarian | Google, Inc. |kevinb at 
> <mailto:kevinb at>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the amber-spec-experts mailing list