Skip to content

Go rollback and remove in a go.work member stay silent about a stale go work vendor modules.txt, so every workspace build fails with "inconsistent vendoring" #1766

Closed

Description

[agent] Found by the scheduled Go modules bug-hunt routine (ledger #317).

Summary

The #343 fix (#1357) warns go_vendor_modules_txt_out_of_sync when a committed vendor directory still records a socket-patch replacement that go.mod no longer has. In a workspace, this only works when the patched module is the go.work root (use .). For any other member (use ./a), go work vendor records the member's replace relative to the workspace root:

# example.com/upstream v1.0.0 => ./a/.socket/go-patches/example.com/upstream@v1.0.0

detect_owner (crates/socket-patch-core/src/vendor/go_mod_edit.rs:88) only treats a target as socket-owned when it starts with ./.socket/go-patches/ or ./.socket/vendor/golang/. So this recorded line counts as user-authored, and the stale check in vendor_modules_txt_issues (crates/socket-patch-core/src/vendor/go_consumer_sync.rs:580, recorded.iter().filter(|r| r.socket_owned())) skips it.

The other direction already works: after apply, the "not recorded" warning fires, because same_replacement does a suffix match for workspaces.

Impact

After rollback or remove in a non-root member of a vendored workspace, both commands exit 0 with no warning, and apply --check says "No patches to check" (exit 0). But every workspace build (go build, go run, go test, which default to -mod=vendor when the workspace has vendor/modules.txt) now fails:

go: inconsistent vendoring in …/ws:
	example.com/upstream@v1.0.0: is marked as replaced in vendor/modules.txt, but not replaced in the workspace

The same rollback in a use . root module does warn, which is the documented behaviour.

Repro

Hermetic file GOPROXY, hand-staged .socket/manifest.json plus blob (the tests/e2e_golang_build.rs shape). Go 1.22+ (go work vendor).

# ws/go.work:  go 1.22 \n use ./a
# ws/a/go.mod: module example.com/a; require example.com/upstream v1.0.0; main.go prints upstream.Greeting()
# ws/a/.socket/manifest.json + blob patching lib.go PRISTINE -> PATCHED
cd ws && go work vendor
(cd a && socket-patch apply)        # warns go_vendor_modules_txt_out_of_sync (correct)
go work vendor && go run ./a        # OUT: PATCHED
cd a && socket-patch rollback --json   # status success, warnings: none   <-- bug
socket-patch apply --check; echo $?    # "No patches to check.", 0
cd .. && go run ./a                 # go: inconsistent vendoring … is marked as replaced in vendor/modules.txt, but not replaced in the workspace

socket-patch remove pkg:golang/example.com/upstream@v1.0.0 behaves the same way. Control: the same steps with use . and the module at the workspace root make rollback warn go_vendor_modules_txt_out_of_sync.

Expected vs actual

  • Expected, per docs/ecosystems.md (warning table, go_vendor_modules_txt_out_of_sync): the warning fires for "a committed vendor/ directory (go mod vendor; go work vendor for a workspace) whose vendor/modules.txt … still records one that was removed", with the fix go work vendor.
  • Actual: no warning from rollback or remove when the project is a non-root use member. Exit 0, and the workspace no longer builds.

Matrix (Linux)

go use ./a member: rollback/remove warn use . root: rollback warns
1.22.12 fail (silent, build broken) —
1.24.7 fail (3×, rollback and remove) pass
1.26.8 fail —
< 1.22 n/a (no go work vendor) n/a

macOS and Windows: untested (probe branches are blocked in this routine). Vendored mode (.socket/vendor/golang/) goes through the same detect_owner prefix check, so it is likely affected, but I didn't test it (it needs a mock patch service).

The open PR stack #1764/#1765 does not fix it: I built #1765's head (pr1765). There a single-member patch still goes into a/go.mod, and the same repro gives rollback warnings: [] and then "inconsistent vendoring".

Suspect code

  • crates/socket-patch-core/src/vendor/go_consumer_sync.rs:580: the stale loop filters recorded by socket_owned(). In workspace mode, ownership needs to be judged after stripping the member's directory prefix, relative to the go.work directory (as same_replacement already does for the forward check).
  • crates/socket-patch-core/src/vendor/go_mod_edit.rs:88: detect_owner is root-anchored by design (a user's ../sibling/.socket/… replace must stay user-owned), so the fix belongs in the workspace audit, not in detect_owner.

Tested on main b787454 (5.0.1+171).

Activity

  1. mikolalysenko commented on Oct 28, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triage: priority:p2 (Go modules). Confirmed on main b787454: the stale-record loop in vendor_modules_txt_issues (crates/socket-patch-core/src/vendor/go_consumer_sync.rs:580) still filters recorded by the root-anchored socket_owned(), so a go work vendor line such as => ./a/.socket/go-patches/... is never judged stale. The forward check already handles this through same_replacement. Not a duplicate. No open PR covers it: #1752/#1755 change Go version selection, and #1763–#1765 change the workspace model/writer. It does not share a root cause with #549, which is about go.sum restore after go mod tidy.


    Generated by Claude Code

  2. mikolalysenko commented on Oct 28, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue (shared root cause: the workspace modules.txt stale check judges socket ownership of a recorded replace by a root-anchored prefix, so a non-root member's ./a/.socket/... line never counts). Branch: agent/fix-go-work-vendor-stale-member. Claim-ID: 2026-10-28T04:21:12Z-98165a


    Generated by Claude Code

  3. mikolalysenko commented on Oct 28, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Fix in progress in draft PR #1767.


    Generated by Claude Code

  4. added a commit that references this issue on Oct 28, 2026
    92e6d2f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions