Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrading from 1.4.9 to more recent versions throws NoSuchElementException #236

Closed
chris-ryan-square opened this issue Nov 14, 2021 · 21 comments

Comments

@chris-ryan-square
Copy link

I've tried upgrading from 1.4.9 to 1.4.10 and above, but I get the following stacktrace:

java.util.NoSuchElementException: List is empty.
        at kotlin.collections.CollectionsKt___CollectionsKt.first(_Collections.kt:212)
        at com.sksamuel.hoplite.decoder.DataClassDecoder.safeDecode(DataClassDecoder.kt:116)
        at com.sksamuel.hoplite.decoder.NullHandlingDecoder$DefaultImpls.decode(Decoder.kt:85)
        at com.sksamuel.hoplite.decoder.DataClassDecoder.decode(DataClassDecoder.kt:28)
        at com.sksamuel.hoplite.ConfigLoader.decode(ConfigLoader.kt:400)
        at com.sksamuel.hoplite.ConfigLoader.loadConfig(ConfigLoader.kt:386)
...

I haven't narrowed what in our config is causing this as yet, but if I do, I'll update the issue with the details.

@sksamuel
Copy link
Owner

sksamuel commented Nov 15, 2021

Is that the only thing you changed ?
Also, did you try 1.4.14 ?

@sksamuel
Copy link
Owner

The class in question, does it have multiple constructors ?

@chris-ryan-square
Copy link
Author

I tried 1.4.10, 1.4.13 and 1.4.14.

I haven't worked out which particular part of the config it's breaking on. The main config class is a data class that includes a number of other data classes (which in turn do the same).

I have no extra explicit constructors, although some fields do have default values (does that make another constructor?). If it matters, some of these default values are null.

And my config is loaded combining 2 yaml files.

@sksamuel
Copy link
Owner

sksamuel commented Nov 15, 2021 via email

@chris-ryan-square
Copy link
Author

I started on extracting it out to a test case for you, but somehow in the process of doing the sanitisation it's now working fine. So, I have to go back to the start of the sanitisation process and work through to find the real issue.

@sksamuel
Copy link
Owner

sksamuel commented Nov 15, 2021 via email

@chris-ryan-square
Copy link
Author

Another update. I've got a separate project where I'm trying to reproduce the error. I went back to using copies of various files to run the test - passes fine.

My various data classes are across a number of modules/projects, so the only thing I can think of right now is something weird with the classpath. Shall investigate more. Very bizarre.

@sksamuel
Copy link
Owner

sksamuel commented Nov 16, 2021 via email

@sksamuel
Copy link
Owner

If so (that 1.4.9 works again) then my guess is this commit: 4e9f584

Which is why I was asking about multiple constructors.

@chris-ryan-square
Copy link
Author

Yes, it works fine with 1.4.9.

I wrote another test in our actual code and the 1.4.14 works fine as well with the real classes and config.

I don't know why yet, but the error happens when the code is running the application - which happens to be bundled in a shadow jar.

@chris-ryan-square
Copy link
Author

I'll be closing this issue as the fault is 100% in my camp. It was a gradle build file misconfiguration that was including libraries it should not have been in the final shadow jar. The changes in 1.4.10 were enough to trigger a time-bomb that was waiting to go off.

@chris-ryan-square
Copy link
Author

Spoke too soon. My changes + last lot of tests were with the 1.4.9 version. Still got the issue. More investigations.

@mneundorfer
Copy link

mneundorfer commented Nov 16, 2021

I can confirm this issue

For me the problem disappears after getting rid of @ConfigAlias in my configuration class. Not sure about the underlying issue though...

edit: I could track down the cause to the value defined in ConfigAlias containing a dot ., such as app.host. It seems that using appHost instead solves the problem.

@sksamuel
Copy link
Owner

sksamuel commented Nov 16, 2021 via email

@chris-ryan-square
Copy link
Author

@mneundorfer if you've got an example that shows the issue that you can share, please do.

@chris-ryan-square
Copy link
Author

Got a simple replication for you:

import com.sksamuel.hoplite.ConfigLoader
import com.sksamuel.hoplite.yaml.YamlPropertySource
import io.kotest.core.spec.style.FreeSpec

data class A(
  val foo: Foo = Foo()
)

data class Foo(
  val x: String = "x"
)

class StartHereConfigTest : FreeSpec({

  val config = "{" +
      "}"

  "Bug Reproduce" {
    val a = ConfigLoader.Builder()
      .addSource(YamlPropertySource(config))
      .build()
      .loadConfigOrThrow<A>()
  }

})

@chris-ryan-square
Copy link
Author

chris-ryan-square commented Nov 17, 2021

Essentially, buried in our config we've got an "optional" config data class that has defaults in it (other data classes - not sure if that's important or not). Those fields have default values. And our config has no entries for these defaults, so I assume they get an "empty" block to parse?

@sksamuel
Copy link
Owner

So the config data class is itself not nullable, but each of the parameters of that class are optional as they provide defaults, and with the empty block, the whole thing falls over ?

If so, I understand the issue, and will work on a fix.

@chris-ryan-square

@chris-ryan-square
Copy link
Author

Yes, it took a while to track down as I was thinking about null values. Anyway, the test above should help.

sksamuel added a commit that referenced this issue Nov 17, 2021
@sksamuel
Copy link
Owner

Ok publishing 1.4.15 now with fix.

@chris-ryan-square
Copy link
Author

Retested with 1.4.15 - all good now, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants