Tests failing after migrating from akka 2.5.x to akka 2.6.x

Hi guys

Some of my akka-stream unit tests are failing in a weird way after updating akka from 2.5 to 2.6. All of the tests that are failing are testing exceptional cases with restartSources/restartFlows. All the tests that were expecting certain domain exceptions whenever a stream fails are now receiving a com.typesafe.config.ConfigException$BadPath: path parameter: Invalid path '': path has a leading, trailing, or two adjacent period '.' (use quoted "" empty string if you want an empty element)

Here’s an example:

"fail when retries have been exhausted" in new Context {
      val source = Source.single(Checkpointable(envelopeWithEventAndState, checkpointer))

      (metrics
        .getCounter(_: String, _: List[Tag]))
        .expects("event_consumed",
                 List(Tag(key = "success", value = Some("true")),
                      Tag(key = "event", value = Some("FooEvent"))))
        .returns(TestCounter)

      // Failure cases
      (s3AsyncClient
        .putObject(_: PutObjectRequest, _: AsyncRequestBody))
        .expects(
          PutObjectRequest
            .builder()
            .bucket(bucketName)
            .build(),
      
             *
        )
        .returns({
          val fut = new CompletableFuture[PutObjectResponse]()
          fut.completeExceptionally(SdkClientException.create(""))
          fut
        })
        .twice()

      // Failure cases
      (metrics
        .getCounter(_: String, _: List[Tag]))
        .expects("s3_upload", List(Tag(key = "success", value = Some("false"))))
        .returns(TestCounter)
        .twice()

      whenReady(source.via(handleEnvelopeFlow).runWith(Sink.ignore).failed) { res =>
        // this fails, res is an com.typesafe.config.ConfigException$BadPath exception
        res shouldBe an[SdkClientException]
      }
    }

So this particular test is verifying that the stream which is trying to upload objects into S3 fails once the max number of retries (1 in this case) have been exceeded. This worked fine in 2.5 of akka but is failing in 2.6

Hi @Olafur,

this looks like an issue reading the config. Do you have a longer stack trace?
Also, could you review the version of typesafe-config.jar on your classpath before and after bumping Akka 2.5 and 2.6.
Finally, since the error is on reading the config files, it’s possible the problem is related to a third party library which depends on some default setting available in a transitive library.

Longstory short, please provide more context around the exception you mentioned. :-)

It looks like typesafe-config.jar is not on the classpath, or maybe it’s transitively there (I’m using pants build tool so i’m not 100% sure on how to list all targets on the classpath). But what I could find on the classpath relating to akka is:

com.typesafe.akka:akka-testkit_2.12:2.6.5
com.typesafe.akka:akka-stream-testkit_2.12:2.6.5
com.typesafe.akka:akka-stream_2.12:2.6.5
com.typesafe.akka:akka-actor_2.12:2.6.5
com.typesafe.akka:akka-slf4j_2.12:2.6.5

here is the full stack trace:

handleEnvelopeFlow should fail when retries have been exhausted(S3SyncFlowSpec)
                     org.scalatest.exceptions.TestFailedException: com.typesafe.config.ConfigException$BadPath: path parameter: Invalid path '': path has a leading, trailing, or two adjacent period '.' (use quoted "" empty string if you want an empty element) was not an instance of software.amazon.awssdk.core.exception.SdkClientException, but an instance of com.typesafe.config.ConfigException$BadPath
                     	at org.scalatest.MatchersHelper$.newTestFailedException(MatchersHelper.scala:138)
                     	at org.scalatest.matchers.TypeMatcherHelper$.assertAnType(TypeMatcherHelper.scala:162)
                     	at S3SyncFlowSpec$$anon$5.$anonfun$new$5(S3SyncFlowSpec.scala:199)
                     	at org.scalatest.concurrent.Futures.whenReady(Futures.scala:677)
                     	at org.scalatest.concurrent.Futures.whenReady$(Futures.scala:675)
                     	at S3SyncFlowSpec.whenReady(S3SyncFlowSpec.scala:35)
                     	at S3SyncFlowSpec$$anon$5.<init>(S3SyncFlowSpec.scala:198)
                     	at S3SyncFlowSpec.$anonfun$new$4(S3SyncFlowSpec.scala:160)
                     	at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
                     	at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
                     	at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
                     	at org.scalatest.Transformer.apply(Transformer.scala:22)
                     	at org.scalatest.Transformer.apply(Transformer.scala:20)
                     	at org.scalatest.WordSpecLike$$anon$1.apply(WordSpecLike.scala:1078)
                     	at org.scalatest.TestSuite.withFixture(TestSuite.scala:196)
                     	at org.scalatest.TestSuite.withFixture$(TestSuite.scala:195)
                     	at S3SyncFlowSpec.org$scalamock$scalatest$AbstractMockFactory$$super$withFixture(S3SyncFlowSpec.scala:35)
                     	at org.scalamock.scalatest.AbstractMockFactory.$anonfun$withFixture$1(AbstractMockFactory.scala:35)
                     	at org.scalamock.MockFactoryBase.withExpectations(MockFactoryBase.scala:55)
                     	at org.scalamock.MockFactoryBase.withExpectations$(MockFactoryBase.scala:47)
                     	at S3SyncFlowSpec.withExpectations(S3SyncFlowSpec.scala:35)
                     	at org.scalamock.scalatest.AbstractMockFactory.withFixture(AbstractMockFactory.scala:34)
                     	at org.scalamock.scalatest.AbstractMockFactory.withFixture$(AbstractMockFactory.scala:31)
                     	at S3SyncFlowSpec.withFixture(S3SyncFlowSpec.scala:35)
                     	at org.scalatest.WordSpecLike.invokeWithFixture$1(WordSpecLike.scala:1076)
                     	at org.scalatest.WordSpecLike.$anonfun$runTest$1(WordSpecLike.scala:1088)
                     	at org.scalatest.SuperEngine.runTestImpl(Engine.scala:289)
                     	at org.scalatest.WordSpecLike.runTest(WordSpecLike.scala:1088)
                     	at org.scalatest.WordSpecLike.runTest$(WordSpecLike.scala:1070)
                     	at S3SyncFlowSpec.runTest(S3SyncFlowSpec.scala:35)
                     	at org.scalatest.WordSpecLike.$anonfun$runTests$1(WordSpecLike.scala:1147)
                     	at org.scalatest.SuperEngine.$anonfun$runTestsInBranch$1(Engine.scala:396)
                     	at scala.collection.immutable.List.foreach(List.scala:392)
                     	at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:384)
                     	at org.scalatest.SuperEngine.runTestsInBranch(Engine.scala:373)
                     	at org.scalatest.SuperEngine.$anonfun$runTestsInBranch$1(Engine.scala:410)
                     	at scala.collection.immutable.List.foreach(List.scala:392)
                     	at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:384)
                     	at org.scalatest.SuperEngine.runTestsInBranch(Engine.scala:379)
                     	at org.scalatest.SuperEngine.runTestsImpl(Engine.scala:461)
                     	at org.scalatest.WordSpecLike.runTests(WordSpecLike.scala:1147)
                     	at org.scalatest.WordSpecLike.runTests$(WordSpecLike.scala:1146)
                     	at S3SyncFlowSpec.runTests(S3SyncFlowSpec.scala:35)
                     	at org.scalatest.Suite.run(Suite.scala:1147)
                     	at org.scalatest.Suite.run$(Suite.scala:1129)
                     	at S3SyncFlowSpec.org$scalatest$WordSpecLike$$super$run(S3SyncFlowSpec.scala:35)
                     	at org.scalatest.WordSpecLike.$anonfun$run$1(WordSpecLike.scala:1192)
                     	at org.scalatest.SuperEngine.runImpl(Engine.scala:521)
                     	at org.scalatest.WordSpecLike.run(WordSpecLike.scala:1192)
                     	at org.scalatest.WordSpecLike.run$(WordSpecLike.scala:1190)
                     	at S3SyncFlowSpec.org$scalatest$BeforeAndAfterAll$$super$run(S3SyncFlowSpec.scala:35)
                     	at org.scalatest.BeforeAndAfterAll.liftedTree1$1(BeforeAndAfterAll.scala:213)
                     	at org.scalatest.BeforeAndAfterAll.run(BeforeAndAfterAll.scala:210)
                     	at org.scalatest.BeforeAndAfterAll.run$(BeforeAndAfterAll.scala:208)
                     	at S3SyncFlowSpec.run(S3SyncFlowSpec.scala:35)
                     	at org.scalatest.junit.JUnitRunner.run(JUnitRunner.scala:99)
                     	at __shaded_by_pants__.org.pantsbuild.tools.junit.impl.CompositeRequestRunner.runChild(CompositeRequestRunner.java:66)
                     	at __shaded_by_pants__.org.pantsbuild.tools.junit.impl.ConcurrentCompositeRequestRunner$1$1.run(ConcurrentCompositeRequestRunner.java:37)
                     	at __shaded_by_pants__.org.pantsbuild.tools.junit.impl.ConcurrentRunnerScheduler.finished(ConcurrentRunnerScheduler.java:89)
                     	at __shaded_by_pants__.org.pantsbuild.tools.junit.impl.ConcurrentCompositeRequestRunner$1.evaluate(ConcurrentCompositeRequestRunner.java:46)
                     	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
                     	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
                     	at __shaded_by_pants__.org.pantsbuild.tools.junit.impl.ConsoleRunnerImpl.runLegacy(ConsoleRunnerImpl.java:539)
                     	at __shaded_by_pants__.org.pantsbuild.tools.junit.impl.ConsoleRunnerImpl.run(ConsoleRunnerImpl.java:455)
                     	at __shaded_by_pants__.org.pantsbuild.tools.junit.impl.ConsoleRunnerImpl.main(ConsoleRunnerImpl.java:843)
                     	at org.pantsbuild.tools.junit.ConsoleRunner.main(ConsoleRunner.java:12)