Ryan Trontz
07/07/2025, 4:00 PM> Could not resolve com.puppycrawl.tools:checkstyle:9.3.
Required by:
project :<project-path>
> Could not resolve com.puppycrawl.tools:checkstyle:9.3.
> Could not parse POM https://<repository-host>/<repository-path>/com/puppycrawl/tools/checkstyle/9.3/checkstyle-9.3.pom
> Already seen doctype.
What appears to be happening is that Gradle is receiving a raw HTML file instead of a POM file. It's coming from Cloudflare, before the request even reaches our repository, where checkstyle has been successfully proxied and stored.
What's really problematic is that his appears to corrupt the local gradle cache, and even after re-auth-ing with CF, the only way to fix this is to either re-run the build with --refresh-dependencies
or clear the gradle cache. For backend repos this is a minor inconvenience, for android repos it's a nonstarter.
Now, we also ship a settings-plugin that needs to be resolved from our repository, so this issue can bite us first thing in the build process, so we can't even bake in checks for this in our plugins/build scripts.
Lastly, while the cloudflare CLI has a bunch of great commands, it does not have a command that we can use to programmatically detect this state.
🤔 Possible Solutions
init script -- push an init script to everyone's ~/.gradle/init.d
directory that checks for required credentials, and validates the network connection and access via HTTP request. Functionally, this works, but after reading the the configuration cache docs , i'm concerned it won't be invoked on every build, thus defeating the purpose.
is there a gradle property/setting I need to tweak so we don't ingest/store these HTML files?
is there something else I'm just not thinking of?
Open to try any ideas and hear any feedback short of "don't use the VPN", because that's out of my hands.
Thanks for reading!Matthew Von-Maszewski
07/07/2025, 4:24 PMephemient
07/07/2025, 5:16 PMephemient
07/07/2025, 5:23 PMephemient
07/07/2025, 5:28 PMVladimir Sitnikov
07/07/2025, 6:30 PMephemient
07/07/2025, 6:32 PMRyan Trontz
07/07/2025, 6:43 PMRyan Trontz
07/07/2025, 6:43 PMVladimir Sitnikov
07/07/2025, 6:46 PMephemient
07/07/2025, 6:47 PMVladimir Sitnikov
07/07/2025, 6:49 PMVladimir Sitnikov
07/07/2025, 6:50 PMephemient
07/07/2025, 6:51 PMRyan Trontz
07/07/2025, 8:14 PMAlready seen DOCTYPE
Vampire
07/07/2025, 11:29 PMpush an init script to everyone'sThat is not an issues, because the dependency resolution result is part of the configuration cache entry. If a configuration cache entry is reused, there will be no dependency resolution done. If dependency resolution needs to be done, then a new configuration cache entry will be created.directory that checks for required credentials, and validates the network connection and access via HTTP request. Functionally, this works, but after reading the the configuration cache docs , i'm concerned it won't be invoked on every build, thus defeating the purpose.~/.gradle/init.d
Open to try any ideas and hear any feedback short of "don't use the VPN", because that's out of my hands.Just a wild idea, but you asked for it. 😄 If CF really answers with a non-sense response but HTTP 200 result code, you could have a proxy on the developer machine that is used by the Gradle builds that verifies the connection or the response to not be HTTP for a requested POM and return a proper error HTTP response instead. But I actually assume that CF is properly answering with a non-200 response. But Gradle also remembers that failure-to-resolve for a while unless the retry timeout is expired or you use the manual
--refresh-dependencies
.
And in that case, such a proxy would probably also not help any further.
If a broken download corrupts Gradle's cache, then it sounds as a severe caching issue to meAfair the cache is not corrupt, it rightfully remembers that the resolution failed until the retry timeout expired or you tell it manually to retry.
checksums [...] aren't checked by defaultI wonder whether this might be a bug or should be reported as feature request. It saves the effort of downloading the checksum file and calculating the checksum, but for the price of not detecting download errors or bitflips or ...
For each file that is the repository there must be a file containing the checksum of the file, typically md5 or sha1
[...]
Maven2 layout says the checksum is mandatoryWhile not every repository follows this "must", it is pretty useless anyway, as it just says "typically md5 or sha1", but it does not require any specific checksum, so even when adhering to the "must", no consumer could rely on the file being there, as it could be any algorithm. 😕
ephemient
07/07/2025, 11:32 PMVladimir Sitnikov
07/08/2025, 8:51 AMin OP’s case, the checksum file will fail to be correctly fetched correctly due to network conditions (same as the artifact itself)If’ve filed https://github.com/gradle/gradle/issues/34158 so Gradle team could reconsider and start requiring at least one checksum for the retrieved artifacts. Frankly speaking, I can hardly imagine a case when the repository misses checksums, and if users really have those types of repositories, they could opt-out of the checksum validation.
Adam
07/08/2025, 3:32 PMephemient
07/08/2025, 3:37 PMVampire
07/08/2025, 3:41 PMconfigurations.matching { it.isCanBeResolved }.configureEach {
withDependencies {
// start the proxy
}
}
and same for buildscript
configurations.
The proxy-starting can be done as an auto-closeable shared build service then it is also shut down at the end of the build.Adam
07/08/2025, 4:09 PMRyan Trontz
07/08/2025, 7:59 PMRyan Trontz
07/08/2025, 8:01 PMephemient
07/08/2025, 8:01 PMRyan Trontz
07/08/2025, 8:02 PMephemient
07/08/2025, 8:04 PMRyan Trontz
07/09/2025, 4:21 PM