title: Scala - InvalidClassException: no valid constructor
body: <p>I created a <code>Serializable</code> version of Guava's <code>ImmutableRangeMap</code> and <code>Builder</code> in Scala in order to use in my Spark application. I have a zero argument constructor in my <code>SerializableImmutableRangeMap</code> as well, so why do I get <code>InvalidClassException: no valid constructor</code> when I run my Spark application?</p>
  
  <p>Here is my <code>SerializableImmutableRangeClass</code> object and class:</p>
  
  <pre><code>object SerializableImmutableRangeMap extends Serializable {
    final class SerializableBuilder[K &lt;: Comparable[_], V]() extends Serializable {
      val keyRanges: RangeSet[K] = TreeRangeSet.create()
      val rangeMap: RangeMap[K, V] = TreeRangeMap.create()
  
      def put(range: Range[K], value: V): SerializableBuilder[K, V] = {
        checkNotNull(range)
        checkNotNull(value)
        checkArgument(!range.isEmpty(), "Range must not be empty, but was %s", range)
        if (!keyRanges.complement().encloses(range)) {
          // it's an error case; we can afford an expensive lookup
          for (entry: Entry[Range[K], V] &lt;- JavaConversions.asScalaSet(rangeMap.asMapOfRanges().entrySet())) {
            val key: Range[K] = entry.getKey()
            if (key.isConnected(range) &amp;&amp; !key.intersection(range).isEmpty()) {
              throw new IllegalArgumentException(
                  "Overlapping ranges: range " + range + " overlaps with entry " + entry)
            }
          }
        }
        keyRanges.add(range)
        rangeMap.put(range, value)
        this
      }
  
      def putAll(rangeMap: RangeMap[K, _ &lt;: V]): SerializableBuilder[K, V] = {
        for (entry &lt;- JavaConversions.asScalaSet(rangeMap.asMapOfRanges().entrySet())) {
          put(entry.getKey(), entry.getValue())
        }
        this
      }
  
      def build(): SerializableImmutableRangeMap[K, V] ={
        val map: java.util.Map[Range[K], V] = rangeMap.asMapOfRanges()
        val rangesBuilder: ImmutableList.Builder[Range[K]] = new ImmutableList.Builder[Range[K]](map.size())
        val valuesBuilder: ImmutableList.Builder[V] = new ImmutableList.Builder[V](map.size())
        for (entry: Entry[Range[K], V] &lt;- JavaConversions.asScalaSet(map.entrySet())) {
          rangesBuilder.add(entry.getKey())
          valuesBuilder.add(entry.getValue())
        }
        return new SerializableImmutableRangeMap[K, V](rangesBuilder.build(), valuesBuilder.build())
      }
    }
  
  def builder[K &lt;: Comparable[_], V](): SerializableBuilder[K, V] = {
      new SerializableBuilder[K, V]()
    }
  }
  
  class SerializableImmutableRangeMap[K &lt;: Comparable[_], V](ranges: ImmutableList[Range[K]], values: ImmutableList[V]) extends ImmutableRangeMap[K, V](ranges, values) with Serializable {
    def this() {
      this(ImmutableList.of(), ImmutableList.of())
    }
  }
  </code></pre>
  
  <p>And the stack trace:</p>
  
  <pre><code>java.io.InvalidClassException: com.google.common.collect.SerializableImmutableRangeMap; no valid constructor
          at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:150)
          at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:768)
          at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1775)
          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
          at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)
          at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)
          at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
          at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)
          at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)
          at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
          at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)
          at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)
          at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
          at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)
          at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)
          at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
          at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1707)
          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1345)
          at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)
          at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)
          at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
          at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)
          at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)
          at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
          at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)
          at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)
          at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
          at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
          at scala.collection.immutable.$colon$colon.readObject(List.scala:362)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
          at java.lang.reflect.Method.invoke(Method.java:483)
          at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
          at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1896)
          at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
          at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)
          at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)
          at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
          at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)
          at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)
          at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
          at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
          at org.apache.spark.serializer.JavaDeserializationStream.readObject(JavaSerializer.scala:68)
          at org.apache.spark.serializer.JavaSerializerInstance.deserialize(JavaSerializer.scala:94)
          at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:60)
          at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:41)
          at org.apache.spark.scheduler.Task.run(Task.scala:64)
          at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:203)
          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
          at java.lang.Thread.run(Thread.java:745)
  </code></pre>