title: Kodein + Ktor = mutation attempt of frozen kotlin.collections.HashMap - why?
body: <p>I have been struggling with this exception for couple of days recently.</p>
  <p>I have a kotlin multiplatform project with these dependencies:</p>
  <ul>
  <li>kotlin=1.5.10</li>
  <li>kodein=7.6.0</li>
  <li>ktor=1.6.0 (uses kotlin coroutines 1.5.0-native-mt internally)</li>
  </ul>
  <p>And I have been getting mentioned exception while trying to use httpClient in native:</p>
  <pre><code>    at kotlin.Throwable#&lt;init&gt;(/Users/teamcity3/buildAgent/work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/Throwable.kt:23)
      at kotlin.Exception#&lt;init&gt;(/Users/teamcity3/buildAgent/work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/Exceptions.kt:23)
      at kotlin.RuntimeException#&lt;init&gt;(/Users/teamcity3/buildAgent/work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/Exceptions.kt:34)
      at kotlin.native.concurrent.InvalidMutabilityException#&lt;init&gt;(/Users/teamcity3/buildAgent/work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/native/concurrent/Freezing.kt:22)
      at &lt;global&gt;.ThrowInvalidMutabilityException(/Users/teamcity3/buildAgent/work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/native/concurrent/Internal.kt:93)
      at &lt;global&gt;.MutationCheck(Unknown Source)
      at kotlin.collections.HashMap.&lt;set-length&gt;#internal(/Users/teamcity3/buildAgent/work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/collections/HashMap.kt:16)
      at kotlin.collections.HashMap#addKey(/Users/teamcity3/buildAgent/work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/collections/HashMap.kt:292)
      at kotlin.collections.HashMap#put(/Users/teamcity3/buildAgent/work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/collections/HashMap.kt:68)
      at org.kodein.di.internal.DITreeImpl#find(/Users/runner/work/Kodein-DI/Kodein-DI/kodein-di/src/commonMain/kotlin/org/kodein/di/internal/DITreeImpl.kt:132)
      at org.kodein.di.DITree#find$default(/Users/runner/work/Kodein-DI/Kodein-DI/kodein-di/src/commonMain/kotlin/org/kodein/di/DITree.kt:36)
      at org.kodein.di.internal.DIContainerImpl#factory(/Users/runner/work/Kodein-DI/Kodein-DI/kodein-di/src/commonMain/kotlin/org/kodein/di/internal/DIContainerImpl.kt:158)
      at org.kodein.di.DIContainer#factory$default(/Users/runner/work/Kodein-DI/Kodein-DI/kodein-di/src/commonMain/kotlin/org/kodein/di/DIContainer.kt:32)
      at org.kodein.di.DIContainer#provider(/Users/runner/work/Kodein-DI/Kodein-DI/kodein-di/src/commonMain/kotlin/org/kodein/di/DIContainer.kt:76)
      at org.kodein.di.DIContainer#provider$default(/Users/runner/work/Kodein-DI/Kodein-DI/kodein-di/src/commonMain/kotlin/org/kodein/di/DIContainer.kt:75)
      at org.kodein.di.internal.DirectDIBaseImpl#Instance(/Users/runner/work/Kodein-DI/Kodein-DI/kodein-di/src/commonMain/kotlin/org/kodein/di/internal/DirectDIImpl.kt:30)
      at InvalidMutabilitySampleTest.&lt;init&gt;$lambda-6$lambda-5$lambda-4$lambda-3$lambda-2#internal(/Users/r.juszczyk/StudioProjects/lmhu-multiplatform-app/MultiplatformApp/src/iosTest/kotlin/InvalidMutabilitySampleTest.kt:26)
      at InvalidMutabilitySampleTest.$&lt;init&gt;$lambda-6$lambda-5$lambda-4$lambda-3$lambda-2$FUNCTION_REFERENCE$3.invoke#internal(/Users/r.juszczyk/StudioProjects/lmhu-multiplatform-app/MultiplatformApp/src/iosTest/kotlin/InvalidMutabilitySampleTest.kt:25)
      at InvalidMutabilitySampleTest.$&lt;init&gt;$lambda-6$lambda-5$lambda-4$lambda-3$lambda-2$FUNCTION_REFERENCE$3.$&lt;bridge-UNNN&gt;invoke(/Users/r.juszczyk/StudioProjects/lmhu-multiplatform-app/MultiplatformApp/src/iosTest/kotlin/InvalidMutabilitySampleTest.kt:25)
      at io.ktor.client.HttpClientConfig.install$&lt;anonymous&gt;_1#internal(/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-core/common/src/io/ktor/client/HttpClientConfig.kt:69)
      at io.ktor.client.HttpClientConfig.$install$&lt;anonymous&gt;_1$FUNCTION_REFERENCE$17.invoke#internal(/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-core/common/src/io/ktor/client/HttpClientConfig.kt:65)
      at io.ktor.client.HttpClientConfig.$install$&lt;anonymous&gt;_1$FUNCTION_REFERENCE$17.$&lt;bridge-UNNN&gt;invoke(/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-core/common/src/io/ktor/client/HttpClientConfig.kt:65)
      at io.ktor.client.features.json.JsonFeature.Feature#prepare(/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-features/ktor-client-json/common/src/io/ktor/client/features/json/JsonFeature.kt:129)
      at io.ktor.client.HttpClientConfig.install$&lt;anonymous&gt;_1-2#internal(/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-core/common/src/io/ktor/client/HttpClientConfig.kt:77)
      at io.ktor.client.HttpClientConfig.$install$&lt;anonymous&gt;_1-2$FUNCTION_REFERENCE$18.invoke#internal(/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-core/common/src/io/ktor/client/HttpClientConfig.kt:74)
      at io.ktor.client.HttpClientConfig.$install$&lt;anonymous&gt;_1-2$FUNCTION_REFERENCE$18.$&lt;bridge-UNNN&gt;invoke(/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-core/common/src/io/ktor/client/HttpClientConfig.kt:74)
      at io.ktor.client.HttpClientConfig#install(/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-core/common/src/io/ktor/client/HttpClientConfig.kt:97)
      at io.ktor.client.HttpClient#&lt;init&gt;(/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-core/common/src/io/ktor/client/HttpClient.kt:172)
      at io.ktor.client.HttpClient#&lt;init&gt;(/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-core/common/src/io/ktor/client/HttpClient.kt:81)
      at io.ktor.client#HttpClient(/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-core/common/src/io/ktor/client/HttpClient.kt:43)
  </code></pre>
  <p>I managed to reproduce that crash in a test:</p>
  <pre><code>class InvalidMutabilitySampleTest {
      val di = DI {
          import(DI.Module(&quot;Some Module&quot;) {
              bind&lt;Json&gt;() with provider {
                  Json {
                      prettyPrint = true
                      isLenient = true
                  }
              }
  
              bind&lt;HttpClient&gt;() with provider {
                  HttpClient{
                      install(JsonFeature) {
                          serializer = KotlinxSerializer(instance())
                      }
                  }
              }
          })
      }
  
      val httpClient: HttpClient by di.instance()
  
      @Test
      fun invalidMutabilityTest() {
          println(httpClient)
      }
  
  }
  </code></pre>
  <p>I also managed to fix it by changing:</p>
  <pre><code>HttpClient{
     install(JsonFeature) {
        serializer = KotlinxSerializer(instance())
     }
  }
  </code></pre>
  <p>to:</p>
  <pre><code>val json = instance&lt;Json&gt;()
  HttpClient{
     install(JsonFeature) {
        serializer = KotlinxSerializer(json)
     }
  }
  </code></pre>
  <p>Then I noticed that HttpClient does a very specific thing - it freezes itself in the init block.
  I managed to reproduce it with this sample code:</p>
  <pre><code>class FrozenConstructor(val block: ()-&gt;Unit) {
      init {
          freeze()
      }
  }
  
  class InvalidMutabilitySampleTest2 {
      val di = DI {
          import(DI.Module(&quot;Some Module&quot;) {
              bind&lt;String&gt;() with provider {
                  &quot;lolo&quot;
              }
  
              bind&lt;FrozenConstructor&gt;() with provider {
                  FrozenConstructor{
                      instance&lt;String&gt;()
                  }
              }
          })
      }
  
      val frozenConstructor: FrozenConstructor by di.instance()
  
      @Test
      fun invalidMutabilityTest() {
          println(frozenConstructor)
      }
  }
  </code></pre>
  <p>So my theory is following:</p>
  <ol>
  <li>kodein tries to provide <code>FrozenConstructor</code> class</li>
  <li><code>FrozenConstructor</code> is created and it freezes itself, and its member which references kodein</li>
  <li>kodein tries to cache provided dependency and try to mutate internal <code>MutableMap</code> which is frozen and everything crashes</li>
  </ol>
  <p>Can someone confirm that this is more or less correct , and correct me if not?</p>
  <p>And also can you guys suggest the best way of handling it, and other pitfalls which are waiting there?</p>
  <p>Is it a kodein bug?</p>
  <p>Why kodein has to store something in a mutable map if I am using <code>with provider</code> not <code>with singleton</code> ?</p>