We have a similar issue even without type erasure, unless we actually walk through Lists and Maps here. Otherwise there could always be something non-serializeable buried deep inside.

I will admit the PersistentMetadataValue class feels a little tacked-on right now. I recently re-worked it, originally I had separate constructors for each type it could accept, which actually works a lot better for compile-time validation, and for sort of nudging callers in the right direction.

But I found myself, internally in the NBTMetadataStore, wanting to just be able to call an Object constructor for convenience.

I could put it back the other way, and put the onus of calling the correct constructed based on the the type of data being stored on the caller (including NBTMetadataStore itself). I kind of liked the forced-type constructors, otherwise there's not much point to this class, honestly.

The Map and List constructors could also do recursive type inspection of contents, but I think that will have the type erasure issue one way or another for any nested Lists or Maps.. right?

Anyway, whatever you think is best- this side of the API is kind of loose to me, I really want it to be better but I'm struggling to find a good fit. Another good point someone brought up earlier, it'd be nice if PersistentMetadataValue could somehow throw an error if added to a non-peristent store, though I don't see a way to make that happen. 

It was suggested that developers might suddenly think all Metadatable stores supported persistence if they just use this special value type, and since that is not true I can see how this may be confusing in general.