Skip to content

scan reports success with 0 packages on a resolved Gradle project because the Gradle cache (~/.gradle/caches/modules-2) is never crawled #349

Description

[agent] Found by the scheduled Gradle bug-hunt routine (ledger #319).

Summary

MavenCrawler treats build.gradle* / settings.gradle* as Java project markers, but then only crawls the Maven local repository ($MAVEN_REPO_LOCAL / $M2_HOME/repository / ~/.m2/repository). Gradle never writes there. It resolves into $GRADLE_USER_HOME/caches/modules-2/files-2.1/<group>/<artifact>/<version>/<sha1>/. On a normal Gradle-only project, scan (agent), scan --mode hosted and scan --mode vendored all return "status": "success", "scannedPackages": 0 and never query the API. As a result:

  • the documented hosted Gradle path (redirect_gradle_manual_snippet) can never fire unless ~/.m2 happens to hold the same GAV from unrelated Maven use;
  • agent mode patches nothing, silently;
  • nothing tells the user that Gradle dependencies weren't looked at.

Repro

mkdir gp && cd gp
echo "rootProject.name = 'gp'" > settings.gradle
cat > build.gradle <<'EOF'
plugins { id 'java' }
repositories { mavenCentral() }
dependencies { implementation 'org.apache.commons:commons-text:1.10.0' }
EOF
gradle dependencies --configuration runtimeClasspath   # populates ~/.gradle/caches/modules-2, no ~/.m2
socket-patch scan --json                 # "status":"success","scannedPackages":0
socket-patch scan --mode hosted --json   # same; redirect.warnings == []

A logging mock on --proxy-url confirms no /patch/batch request is ever sent. As a cross-check, scan --global-prefix ~/.gradle/caches/modules-2/files-2.1 does find commons-text@1.10.0 and commons-lang3@3.12.0 by POM content. So the data is there; it's just not in the discovery roots. (Agent apply couldn't use that root anyway: find_by_purls expects the Maven group/path/artifact/version layout, not Gradle's dotted group + per-file <sha1> directories.)

Expected vs actual

  • Expected: docs/ecosystems.md presents Gradle as handled in hosted mode ("A present build.gradle* / settings.gradle* gets a paste-able exclusiveContent { … } snippet"), and the crawler deliberately accepts Gradle markers (maven_crawler.rs:580). Gradle-resolved dependencies should be discovered, or the scan should at least warn that the Gradle cache isn't supported, instead of reporting a clean success.
  • Actual: silent success with zero packages. Nowhere in README.md / docs/ecosystems.md is agent or hosted discovery for Gradle documented as unsupported (README's VEX table says "no Gradle" only for VEX discovery).

Matrix (Linux; each run twice)

Gradle GRADLE_USER_HOME agent hosted vendored
8.14.3 default ~/.gradle 0 pkgs, success ❌ 0 pkgs, success ❌ 0 pkgs, success ❌
8.14.3 custom dir 0 pkgs, success ❌ 0 pkgs, success ❌ 0 pkgs, success ❌

The cache layout (modules-2/files-2.1) has been the same since Gradle 1.x, so every major is affected. Tested on main f6b7fb9 (4.0.0).

Suspect code

  • crates/socket-patch-core/src/crawlers/maven_crawler.rs:580-605: Gradle markers select only m2_repo_path() (:709).
  • crates/socket-patch-core/src/crawlers/maven_crawler.rs find_by_purls: Maven layout only.

Activity

  1. mikolalysenko commented on Sep 30, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triaged: priority:p3 (Gradle). This isn't a duplicate, and I found no existing fix PR. The cause is that MavenCrawler recognizes Gradle projects but only crawls the Maven local repository, never $GRADLE_USER_HOME/caches/modules-2.


    Generated by Claude Code

  2. mikolalysenko commented on Oct 1, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Re-triage on main 2463257 (#277): still reproduces, on Linux with Gradle 8.14.3.

    The project is gradle-only: settings.gradle, plus a build.gradle that depends on commons-configuration2:2.9.0 and so pulls in commons-text:1.10.0. GRADLE_USER_HOME is warm (caches/modules-2/files-2.1/org.apache.commons/{commons-text,commons-configuration2,commons-lang3} present) and MAVEN_REPO_LOCAL is empty. socket-patch scan --json reports "scannedPackages": 0, the same as with a cold GRADLE_USER_HOME. The only time a gradle-only project scans anything is after vendor, when the committed .socket/vendor/gradle/… tree is counted (scannedPackages: 1).

    Global mode has the same gap. With the same warm GRADLE_USER_HOME and an empty m2, scan -g --json sends a batch request with zero pkg:maven purls (cargo 233, npm 210, pypi 102, gem 17), so Gradle-cached global installs are never reported. The crawler itself can read Gradle's layout, though. scan --global-prefix ~/.gradle/caches/modules-2/files-2.1 correctly yields pkg:maven/org.apache.commons/commons-text@1.10.0, commons-configuration2@2.9.0, commons-lang3@3.12.0 and the rest, 15 purls including parent/BOM poms. So this looks like a missing root, not a parser limitation, and that --global-prefix is a workaround for report-only scans. scan -g --mode hosted and --global-prefix … --mode hosted both refuse correctly (exit 2, "global installs have no project lockfile to redirect").

    The new docs/design/maven-vendoring.md now says "Maven discovery still uses the Maven local repository; a Gradle-only cache is not a Maven discovery source". So this may now count as an intended limitation. However, that sentence is in the vendoring design doc, and the user-facing scan / scan -g output still shows nothing that tells a Gradle user their dependencies were never looked at. That's also true now that v5 scan defaults to hosted mode. I'm leaving the triage call to a maintainer.


    Generated by Claude Code

  3. mikolalysenko commented on Oct 2, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue as part of the full Gradle support campaign (agent / hosted / vendored modes, tested on Gradle 6.9/7.6/8.x/9.x on Linux, macOS and Windows). Branch: feat/gradle-support. Claim-ID: 2026-10-02T13:56:32Z-gradle21


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions