Repository navigation
Vendored Gradle build fails on a stray file such as .DS_Store in the vendored tree, and the fix the error prescribes ("re-run socket-patch vendor") does nothing: vendor says already_vendored and repair is a no-op #656
Description
[agent] Found by the scheduled Gradle bug-hunt routine (ledger #319).
Summary
The vendored Gradle settings script rejects any file in .socket/vendor/gradle/<g>/<a>/<v>/ that isn't in the index. A macOS .DS_Store counts: Finder writes one as soon as someone opens the folder. The build then fails with:
socket-patch: unindexed files in org/apache/commons/commons-text/1.10.0: [.DS_Store]. Restore it from git or re-run `socket-patch vendor`.
Neither remedy in that message works:
socket-patch vendorexits 0 withalready_vendored("artifact and lockfile wiring already in sync") and leaves the stray file where it is, so the build stays broken.socket-patch repairalso exits 0 and changes nothing.- "Restore it from git" doesn't help either: the stray file is untracked (and usually globally ignored), so
git restore/git checkoutdon't remove it.
The CLI also disagrees with itself. vendor --check exits 1 (vendor_check_failed, "unindexed vendored file: …/.DS_Store"), while vendor reports the tree in sync, and vex still emits not_affected for a build that can't configure.
A missing file is handled correctly. If I delete the vendored jar, vendor reports rebuilt and restores it. Only extra files fall through vendor's in-sync check.
Impact
On macOS, browsing the vendored folder in Finder (or a Windows Thumbs.db / desktop.ini, an editor backup, or AppleDouble ._* files from a copy) breaks every local Gradle build of the project. The tool's error message sends the user to two commands that report success and change nothing, so they have to work out for themselves that the file needs deleting by hand (or with git clean). This fails closed (no unpatched artifact is produced), but it is a broken recovery path.
Repro (Linux, main 045d7ec)
mkdir p && cd p && git init -q
echo "rootProject.name = 'p'" > settings.gradle
cat > build.gradle <<'EOF'
plugins { id 'java' }
repositories { mavenCentral() }
dependencies { implementation 'org.apache.commons:commons-text:1.10.0' }
EOF
git add -A && git commit -qm init
# stage a patch for pkg:maven/org.apache.commons/commons-text@1.10.0 in .socket/manifest.json + blob
# (the bug-hunt used prebuilt_common::prepare_command, the same as e2e_vendor_jvm_build.rs)
socket-patch vendor --json --offline # exit 0, applied
gradle dependencies --configuration runtimeClasspath # OK, resolves .socket/vendor/gradle/... (patched)
touch .socket/vendor/gradle/org/apache/commons/commons-text/1.10.0/.DS_Store
gradle dependencies --configuration runtimeClasspath # FAILS: "unindexed files ... [.DS_Store]. ... re-run `socket-patch vendor`"
socket-patch vendor --json --offline # exit 0, skipped/already_vendored; .DS_Store still there
socket-patch repair --json # exit 0, no events
gradle dependencies --configuration runtimeClasspath # still FAILS
socket-patch vendor --check --json # exit 1, vendor_check_failed: unindexed vendored file
socket-patch vex --product pkg:maven/x/p@1 --output v.json # exit 0, not_affected
rm .socket/vendor/gradle/org/apache/commons/commons-text/1.10.0/.DS_Store
gradle dependencies --configuration runtimeClasspath # OK againExpected vs actual
- Expected: the build error's own advice ("re-run
socket-patch vendor") restores a working build.docs/design/maven-vendoring.mdsaysvendor,repairandvendor --checkshare the v5 vendored backend, and that--checkchecks "unindexed files". So the in-sync checkvendorandrepairuse should treat an unindexed file as drift and sweep it (or at least fail with a clear "delete X" message), instead of reportingalready_vendored. Alternatively, the script could ignore well-known OS metadata files (.DS_Store,Thumbs.db,desktop.ini,._*), which Gradle never serves anyway. - Actual:
vendorandrepairexit 0 and change nothing,--checkexits 1, and the build stays broken.
Matrix
| OS | Gradle (JDK) | DSL | Build fails on stray file | vendor re-run fixes it |
repair fixes it |
|---|---|---|---|---|---|
| Linux | 8.14.3 (21) | Groovy | yes | no (already_vendored) |
no |
| Linux | 9.8.0 (21) | Kotlin | yes | no (already_vendored) |
no |
| macOS / Windows | — | — | untested (the logic is OS-independent; .DS_Store / Thumbs.db are where it bites) |
Reproduced twice, on two fresh projects.
Suspect code
crates/socket-patch-core/src/vendor/jvm/socket-patch.settings.gradle:43: theunindexed filesfailure. Line 11 prints the "re-runsocket-patch vendor" advice for every failure, including this one.crates/socket-patch-core/src/vendor/jvm/apply.rs:775-783:vendor --checkdetects the extra file, but thevendor/repairin-sync path (crates/socket-patch-cli/src/commands/vendor.rs:2688,already_vendored) doesn't.
No probe runs (Linux only).
Activity
mikolalysenko commentedon Oct 29, 2026
[agent] Claiming this issue (shared root cause: the JVM vendor in-sync check compares only indexed tree files, so an unindexed file in the vendored tree never counts as drift). Branch: agent/fix-gradle-vendor-unindexed-files. Claim-ID: 2026-10-29T08:21:02Z-dd0c67
Generated by Claude Code
mikolalysenko commentedon Oct 29, 2026
[agent] Draft PR: #1819
Generated by Claude Code
Sweep stray files from vendored JVM trees
Test stray-file recovery with real Gradle
Sweep strays before wiring, outside the commit