See sample code at https://gist.github.com/dreiss/fe353324d4e3f9106af4/9d53619b33b6ab56075d54612b2af29014fa4ed6
On line 141 of the transcript, you can see that the signature for the local variable s2 is the string "Signature", which is of course wrong. It should be "Ljava/util/Set<Lpg/Helper;>;", or the entry removed entirely from the table because Helper is removed from the code. With ProGuard 4.11, it can sometimes point to a "class" entry in the constant table instead of the wrong Utf8Constant, which causes dx to throw an exception when trying to convert the code to dex format. It also causes ProGuard to throw when producing dump.txt. I was not able to get this crash to reproduce with ProGuard 5.0, but I can provide a test case that causes the crash in 4.11 if you want.
I debugged this in 4.11. The problem is that during the shrink pass after the optimization pass, LocalVariableTypeUsageMarker.visitProgramClass sets variableInfoUsed to false because Helper is not used, so LocalVariableTypeUsageMarker.visitLocalVariableTypeInfo does not mark the signature index used. However, the LocalVariableTypeInfo itself is still marked used from the first shrink pass because ClassCleaner does not visit and clean LocalVariableTypeInfo (or LocalVariableInfo). So when ConstantPoolShrinker.shrinkConstantPool runs, constantIndexMap for the signature index just gets set to the next non-removed constant. It might be good to set unused entries in this map to an invalid value to catch bugs like this earlier.
Thanks for your detailed report -- impressive sleuthing! I've fixed ClassCleaner so it also cleans up visitor information in instances of LocalVariable[Type]Info (and ParameterInfo). I'll attach the updated source file. The fix will be included in the upcoming ProGuard 5.0.1. I've also added sanity checks to the shrinking of the constant pool.