In the old code, was it possible for hd to be ListSerializeEnd?  Would the line above the assert not result in a ClassCastException?  Either way, a failure to cast or assertion would prevent deserializing a Nil when a :: was expected.

One way to avoid this is to put the  writeReplace in List, instead of ::  which would cover both sealed subtypes at once.  An additional serialization test with an empty list would be a good idea too.  I'll try that approach.