I feel responsible for part of this as I added the 'collectJarInfos' to
renovate.json and AGENTS.md. While it apparently fixed one condition at
that point, it was still flawed.

So I used Claude to analyze, and here is what came out. Take it for what it 
is...


Short version: it's a build bug, the lockfiles are the
symptom, and neither resolveAndLockAll nor solrbot is really "the" culprit --
they just disagree because we ask them to run different commands.

WTF are all of these `xxxxxxCopy` entries?
------------------------------------------

They come from gradle/validation/jar-checks.gradle, in collectJarInfos:

    configurations.jarValidation.extendsFrom.each {conf ->
      if (excludeRules && excludeRules.size() > 0) {
        conf = conf.copyRecursive()          // <-- here
        conf.canBeResolved = true
        excludeRuleMaps.forEach {conf.exclude(it)}
      }
      if (conf.canBeResolved) {
        queue.addAll(conf.resolvedConfiguration.firstLevelModuleDependencies)
      }
    }

Gradle names the result of Configuration.copyRecursive() "<source>Copy", so
compileClasspath begets compileClasspathCopy, etc. These are throwaway scratch
configurations that exist only while collectJarInfos is executing; they're
there so we can apply jarValidation's exclude rules without those excludes
leaking into the real classpaths.

The reason they end up in the lockfiles is 
gradle/validation/dependencies.gradle:

    dependencyLocking {
      lockAllConfigurations()
    }

copyRecursive() copies the source's resolution strategy, so each clone inherits
active dependency locking -- under its own name.

That also explains why only 4 lockfiles have them: the copy branch only runs
when a project puts an exclude directly on jarValidation, which is exactly
solr/core, solr/test-framework, solr/solrj-zookeeper and solr-ref-guide.

(solr/modules/ltr's "localPythonClientCopy" is a red herring -- a hand-named
configuration that merely ends in "Copy".)

1) Why did solrbot add them?
----------------------------

Because .github/renovate.json tells it to run a different command than
lucene-upgrade.md tells us to run:

    "postUpgradeTasks": {
      "commands": [
        "./gradlew resolveAndLockAll collectJarInfos --write-locks",
        ...

collectJarInfos executes inside a --write-locks build, so the ephemeral clones
get their lock state persisted. dev-docs/gradle-help/dependencies.txt and
AGENTS.md matched the bot; dependency-upgrades.adoc, lucene-upgrade.md and
ui/component-development.adoc all said plain `resolveAndLockAll --write-locks`.
So we had two documented commands producing two different lockfiles.

On timing: you're right that 742c7d99c37 is where ~470 of these appeared. Worth
noting that commit was an actions/setup-java bump -- a pure GitHub-Actions
change that cannot possibly affect Gradle resolution, yet it churned ~920
lockfile lines. It was the first solrbot lockfile regeneration after
0d0a7ab6bf2 (Gradle 9.6.0, three days earlier); before that upgrade the clones
weren't getting written.

2) Why didn't resolveAndLockAll update them?
--------------------------------------------

Because it can't see them. resolveAndLockAll iterates project.configurations:

    project.configurations.findAll {
      it.canBeResolved && ... 
    }.each {it.resolve()}

The clones aren't in that container -- they're created inside collectJarInfos'
task action and thrown away when it finishes. And Gradle's unique-lockfile
writer *merges* rather than rewrites, so entries for configurations that
weren't resolved in this build are preserved verbatim. Hence the split state
you saw: the real configurations moved to 10.5.1, the ghosts stayed at 10.4.0.

That merge behaviour is also why your `updateLicenses` then died at
jar-checks.gradle:134 -- collectJarInfos resolved runtimeClasspathCopy against
lock state you'd just written for the *old* Lucene.

3) Which system is doing the wrong thing?
-----------------------------------------

The build is. Nothing ships out of those clones; they're internal scratch for
license/jar enumeration. Giving them lock state was never useful, and it's not
fixable from either end -- the bot can't stop generating them without dropping
collectJarInfos, and resolveAndLockAll structurally cannot refresh them.

Evidence that this was already actively harmful, on main today:
solr/core/gradle.lockfile pins org.slf4j:slf4j-api at BOTH 2.0.17 (the real
configurations) and 2.0.18 (testRuntimeClasspathCopy only). A version nothing
resolves to any more, sitting in a lockfile.

4) If I delete them, will solrbot add them back?
------------------------------------------------

As things stand, yes -- which is why the fix has to be in the build rather than
in the lockfiles.

I have a draft PR in https://github.com/apache/solr/pull/4794 that attempts to 
fix:

  - jar-checks.gradle: after copyRecursive(), call
    resolutionStrategy.deactivateDependencyLocking() and
    shouldResolveConsistentlyWith(source). The second half is load-bearing:
    dropping locking alone could let a transitive drift away from the tested
    version and silently change which JAR gets license-checked. Pinning to the
    source configuration keeps the versions exact without any lock state.
  - Same treatment for the two copyRecursive() sites in 
gradle/solr/packaging.gradle
    (runtimeLibsCopy, testRuntimeClasspathCopy) -- same latent bug, currently
    invisible only because those tasks don't run during lock generation.
  - Stripped the stale entries from the 4 lockfiles.
  - Dropped collectJarInfos from the lock command in renovate.json,
    dependencies.txt and AGENTS.md, so all six places that document this now
    say the same thing: ./gradlew resolveAndLockAll --write-locks
  - While in renovate.json: its fileFilters was "solr/**/gradle.lockfile",
    which silently discarded bot changes to the root gradle.lockfile,
    platform/gradle.lockfile and settings-gradle.lockfile. Widened.
  - lucene-upgrade.md: the version-catalog snippet was still the old
    "apache-lucene:*=10.3.0" ivy-era syntax. Fixed, plus a note that
    updateLicenses compiles Solr (which answers your "WTF is updateLicenses
    trying to compile all of Solr?" -- collectJarInfos depends on
    jarValidation, which extends compileClasspath, which pulls in project
    dependencies).

Verified:
  - validateJarChecksums / validateJarLicenses pass with zero changes under
    solr/licenses -- i.e. the JAR set is byte-for-byte the same, so
    shouldResolveConsistentlyWith is holding the versions.
  - Running the OLD bot command (resolveAndLockAll collectJarInfos
    --write-locks) no longer reintroduces a single Copy entry.
  - resolveAndLockAll --write-locks twice in a row is now a no-op diff.
  - Bumped apache-lucene to 10.5.1 and re-locked: every lucene coordinate moves
    cleanly, no stragglers at 10.4.0, and collectJarInfos now fails only on the
    genuine API changes rather than on lock state.
  - gradlew check -x test passes.

Jan

> 21. aug. 2026 kl. 23:18 skrev Chris Hostetter <[email protected]>:
> 
> 
> : I think we should dramatically scale back the set of classpaths (aka gradle
> : "configurations"?) in the "lockfile" to reduce problems like this and also
> 
> that feels like a very tangential suggestion to the main concerns in this 
> thread?
> 
> Even if 'runtimeClasspath' had been the only configuration in the 
> lockfiles...
> 
> 1) Solrbot added a runtimeClasspathCopy to a bunch of lockfiles (why?)
> 
> 2) resolveAndLockAll didn't update runtimeClasspathCopy in any file (why?)
> 
> 3) which of those two systems is doing the wrong thing?
> 
> 4) If I try to "fix" the issue by deleting all the runtimeClasspathCopy 
> entries in the lockfiles, is solrbot going to add them back at some point?
> 
> 
> 
> : On Thu, Aug 20, 2026 at 7:08 PM Chris Hostetter <[email protected]>
> : wrote:
> : 
> : >
> : > Spelunking through git history, it looks like this SolrBot PR/commit
> : > added (almost) all of the `xxxxCopy` entries to the `gradle.lockfile`
> : > files...
> : >
> : >  https://github.com/apache/solr/pull/4564
> : >  main:
> : > 
> https://github.com/apache/solr/commit/742c7d99c37701791f998fba9f960db469942218
> : >  10x:
> : > 
> https://github.com/apache/solr/commit/4fafb78192bba240d43c9539f6dcb98fc1ee1be6
> : >
> : >
> : >
> : > hossman@slate:~/lucene/solr [j21] [main] $ git grep Copy | grep -c
> : > gradle.lockfile
> : > 471
> : > hossman@slate:~/lucene/solr [j21] [main] $ git co
> : > 742c7d99c37701791f998fba9f960db469942218~
> : > ...
> : > hossman@slate:~/lucene/solr [j21] [c851aae5c82] $ git grep Copy | grep -c
> : > gradle.lockfile
> : > 1
> : >
> : >
> : >
> : >
> : >
> : >
> : >
> : >
> : >
> : > : Date: Thu, 20 Aug 2026 15:54:23 -0700 (MST)
> : > : From: Chris Hostetter <[email protected]>
> : > : To: Solr Dev <[email protected]>
> : > : Subject: lucene-upgrade.md instructions don't seem to work -- notably:
> : > :     resolveAndLockAll
> : > :
> : > :
> : > : I had a little time this afternoon so I wanted to take a quick stab at
> : > : upgrading Solr to Lucene 10.5.1 just to see what would break, and I feel
> : > like
> : > : either there is a bug in the resolveAndLockAll task or I am seriously
> : > : missunderstanding something with the instructions in lucene-upgrade.md
> : > :
> : > :
> : > :
> : > : Here's what I tried...
> : > :
> : > :
> : > : 1) clean checkout of main, review lucene-upgrade.md
> : > :
> : > : 2) right off the bat, the syntax of gradle/libs.versions.toml does not
> : > match
> : > : what lucene-upgrade.md says to modify.
> : > :
> : > : Instead of a change like this (as documented) ...
> : > :
> : > : - apache-lucene:*=10.3.0
> : > : + apache-lucene:*=10.4.0
> : > :
> : > : ...I assume this is a minor variation in how things are managed, and try
> : > : making a change like this...
> : > :
> : > : -apache-lucene = "10.4.0"
> : > : +apache-lucene = "10.5.1"
> : > :
> : > :
> : > : 3) ./gradlew resolveAndLockAll --write-locks
> : > :
> : > : At first glance this seems to work -- lots of log messages about
> : > "Persisted
> : > : dependency lock state for ..." and `git status` shows a lot of
> : > : `gradle.lockfile` files have been modified.
> : > :
> : > : At this point I move on to the next step of the instructions and get
> : > really
> : > : confused by 2 things -- but before I get to that, let me jump ahead to
> : > what I
> : > : eventually realized...
> : > :
> : > : $ git diff solr/core/gradle.lockfile | grep lucene-core
> : > :
> : > 
> -org.apache.lucene:lucene-core:10.4.0=compileClasspath,compileClasspathCopy,jarValidation,runtimeClasspath,runtimeClasspathCopy,runtimeLibs,testCompileClasspath,testCompileClasspathCopy,testRuntimeClasspath,testRuntimeClasspathCopy
> : > :
> : > 
> +org.apache.lucene:lucene-core:10.4.0=compileClasspathCopy,runtimeClasspathCopy,testCompileClasspathCopy,testRuntimeClasspathCopy
> : > :
> : > 
> +org.apache.lucene:lucene-core:10.5.1=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
> : > :
> : > : ...this seems to have happened in every `gradle.lockfile` modified, for
> : > every
> : > : lucene jar mentioned --- the `xxxxxxCopy` values (no idea what these
> : > are?) all
> : > : stay associated with 10.4.0, while the corisponding `xxxxxx` values are
> : > all
> : > : correctly changed to 10.5.1.
> : > :
> : > :     WTF are all of these `xxxxxxCopy` entries?
> : > :
> : > :
> : > : But as I mentioned -- it took me a while to notice this happened, so
> : > let's
> : > : talk about the other weird thing when i tried to continue with the
> : > : instructions...
> : > :
> : > : 4) ./gradlew updateLicenses
> : > :
> : > : The first thing that confuses the hell out of me when running this
> : > command, is
> : > : that for whatever reason, it depends on `:solr:api:compileJava`
> : > :
> : > : which means it depends on many things, including
> : > `:solr:core:compileJava` --
> : > : which fails because there have been some public (but not intended for 
> end
> : > : user) java API changes in lucene.
> : > :
> : > :    WTF is `updateLicenses` trying to compile all of Solr?
> : > :
> : > : Fortunately the compilation problems seem pretty minor, and easy to fix,
> : > so
> : > : then I retry `./gradlew updateLicenses` ...
> : > :
> : > : ...and that's when everything goes wonky...
> : > :
> : > : 5) REDIX: ./gradlew updateLicenses
> : > :
> : > : We make it past compilation, and quickly get to...
> : > :
> : > :
> : > : ...
> : > : > Task :solr:core:collectJarInfos FAILED
> : > : ...
> : > : FAILURE: Build failed with an exception.
> : > :
> : > : * Where:
> : > : Script '/home/hossman/lucene/solr/gradle/validation/jar-checks.gradle'
> : > line:
> : > : 134
> : > :
> : > : * What went wrong:
> : > : Execution failed for task ':solr:core:collectJarInfos' (registered in
> : > script
> : > : 'gradle/validation/jar-checks.gradle').
> : > : > Could not resolve all dependencies for configuration
> : > : ':solr:core:runtimeClasspathCopy'.
> : > :    > Could not resolve 
> org.apache.lucene:lucene-analysis-kuromoji:10.5.1.
> : > :      Required by:
> : > :          project ':solr:core'
> : > :          project ':solr:core' > project ':platform'
> : > :       > Cannot find a version of
> : > 'org.apache.lucene:lucene-analysis-kuromoji'
> : > : that satisfies the version constraints:
> : > :            Dependency path: 'root' (runtimeClasspathCopy) -->
> : > : 'org.apache.lucene:lucene-analysis-kuromoji:10.5.1'
> : > :            Constraint path: 'root' (runtimeClasspathCopy) -->
> : > : 'org.apache.lucene:lucene-analysis-kuromoji:{strictly 10.4.0}' because
> : > of the
> : > : following reason: Dependency version enforced by Dependency Locking
> : > :            Constraint path: 'root' (runtimeClasspathCopy) --> 'project
> : > : ':platform'' (runtimeElements) -->
> : > : 'org.apache.lucene:lucene-analysis-kuromoji:10.5.1'
> : > :
> : > : ....lots of errors like the above for every lucene jar ...
> : > :
> : > : > There are 19 more failures with identical causes.
> : > :
> : > : * Try:
> : > : > Run with :solr:core:dependencyInsight --configuration
> : > : runtimeClasspathCopy --dependency
> : > org.apache.lucene:lucene-analysis-kuromoji
> : > : to get more insight on how to solve the conflict.
> : > :
> : > : ... lots more "Run with :solr:core:dependencyInsight lines  ...
> : > :
> : > : BUILD FAILED in 24s
> : > :
> : > :
> : > : 5) Try :solr:core:dependencyInsight ?
> : > :
> : > : This fails short and sweet...
> : > :
> : > : ./gradlew :solr:core:dependencyInsight --configuration
> : > runtimeClasspathCopy
> : > : --dependency org.apache.lucene:lucene-analysis-kuromoji
> : > :
> : > : FAILURE: Build failed with an exception.
> : > :
> : > : * What went wrong:
> : > : configuration 'runtimeClasspathCopy' not found in configuration
> : > container for
> : > : project ':solr:core'.
> : > :
> : > : * Try:
> : > : > Run with --stacktrace option to get the stack trace.
> : > : > Run with --info or --debug option to get more log output.
> : > : > Get more help at https://help.gradle.org.
> : > :
> : > : BUILD FAILED in 6s
> : > :
> : > :
> : > :     WTF are all of these `xxxxxxCopy` entries? (REDUX)
> : > :
> : > :
> : > :
> : > :
> : > : It's at this point that i just start greping for '10.4.0' to try and
> : > figure
> : > : out what I screwed up, and realize something is very very wrong with all
> : > of
> : > : our `gradle.lockfile` files
> : > :
> : > :
> : > :
> : > :
> : > : -Hoss
> : > : http://www.lucidworks.com/
> : > :
> : >
> : > -Hoss
> : > http://www.lucidworks.com/
> : >
> : > ---------------------------------------------------------------------
> : > To unsubscribe, e-mail: [email protected]
> : > For additional commands, e-mail: [email protected]
> : >
> : >
> : 
> 
> -Hoss
> http://www.lucidworks.com/
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to