Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

Running Go apply in a second go.work member writes a second replace for the same module@version, so every workspace build fails with "conflicting replacements" while apply, apply --check and VEX all report success

Offen
#531 2 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Anfängerfreundlichkeit
52/100
Issue-Typ
Bug
Klarheit
Größtenteils klar
Aktivitätsstatus
Aktiv
Tech-Stack
go, rust

Rechercherichtung

Start with crates/socket-patch-core/src/patch/redirect/golang_local.rs, especially apply_go_redirect and verify_go_redirect_state, then inspect crates/socket-patch-core/src/vex/discover/golang.rs and crates/socket-patch-cli/src/commands/vex_sources.rs. Reproduce the workspace case using the fixture shape in tests/e2e_golang_build.rs. Done means conflicting workspace replaces are handled explicitly and apply, apply --check, and vex no longer report success for a broken workspace.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

agent:triaged bug bughunt pm:go priority:p2

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

Summary

A go.work workspace has two member modules that both depend on example.com/upstream v1.0.0, and each member has its own .socket/manifest.json with the same patch. Typical cases are a monorepo where every Go module is set up separately, or a root module plus ./tools.

  • Agent-mode apply --cwd a writes replace example.com/upstream v1.0.0 => ./.socket/go-patches/example.com/[email protected] into a/go.mod. In workspace mode a member's replace applies to the whole workspace, so both members now build PATCHED. That part is correct.
  • apply --cwd b then writes the same relative replace into b/go.mod. It resolves to a different directory (b/.socket/go-patches/…). Go rejects that:
    go: conflicting replacements for example.com/[email protected]:
    	…/ws/a/.socket/go-patches/example.com/[email protected]
    	…/ws/b/.socket/go-patches/example.com/[email protected]
    use "go work edit -replace example.com/[email protected]=[override]" to resolve
    
    From then on, every go build / go run / go test in the workspace fails.
  • Even so, both applies exit 0. apply --check reports "Patch redirects are in sync" (exit 0) in both members, and vex attests not_affected (exit 0) in both.

The root-module variant (go.work: use ( . ./tools ), applying in . and then in tools) behaves identically.

This differs from #458 and #393, where the build silently stays unpatched. Here socket-patch turns a working workspace build into a hard failure, and none of its own signals notice.

Impact

Running socket-patch per module in a Go monorepo, which is what you'd expect --cwd to be for, breaks the whole workspace build (local dev and CI). The apply --check CI gate stays green, and the VEX document attests not_affected for a product that can't currently be built.

Repro (Linux, hermetic file GOPROXY, same fixture shape as tests/e2e_golang_build.rs)

export GOTOOLCHAIN=local GOSUMDB=off GOENV=off GOFLAGS= GOPROXY=file://$T/proxy GOMODCACHE=$T/modcache
# example.com/upstream v1.0.0: Greeting() = "PRISTINE"; .socket/manifest.json + blob patch lib.go to "PATCHED"
# ws/a/go.mod: module example.com/a / go 1.21 / require example.com/upstream v1.0.0   (+ go.sum, main.go printing Greeting(), .socket/)
# ws/b/go.mod: module example.com/b / same require, same .socket/ manifest + blob
# ws/go.work:  go 1.21 / use ( ./a ./b )
cd ws
(cd a && go run .); (cd b && go run .)          # OUT: PRISTINE / OUT: PRISTINE
socket-patch apply --offline --cwd a            # exit 0
(cd a && go run .); (cd b && go run .)          # OUT: PATCHED / OUT: PATCHED   (a's replace already covers the workspace)
socket-patch apply --offline --cwd b            # exit 0, "1 of 1 targeted patch applied"
(cd a && go run .)                              # go: conflicting replacements for example.com/[email protected] … (exit 1)
(cd b && go run .)                              # same
socket-patch apply --check --offline --cwd a    # "Patch redirects are in sync (1 redirect checked).", exit 0
socket-patch apply --check --offline --cwd b    # same, exit 0
socket-patch vex --cwd a --offline --product pkg:golang/example.com/a -O v.json   # exit 0, "status": "not_affected"

Reproduced 2× for each variant (two members with no root go.mod, and root . + ./tools) on go 1.24.7, and once each on go 1.22.12 and 1.26.8.

Expected vs actual

  • Expected: docs/ecosystems.md ("Go: directory replaces and go.sum") says user-authored conflicting replacements make apply refuse rather than break the build, and that apply --check gives CI "a read-only audit that the committed redirects still match". README ("socket-patch vex") says the attestation only covers patches that are actually applied. When a go.work that uses the target module also uses another member that already has a Socket replace for the same module@version, apply should do one of two things. It could see that the module is already redirected workspace-wide and skip it (or reuse that copy). Or it could write the replace in go.work, which is the fix Go itself suggests, or refuse with a clear message. apply --check and vex should flag a member replace that conflicts with another workspace member's.
  • Actual: a second, conflicting replace, a broken build, and exit 0 from apply, apply --check and vex.

OS × version

OS go 2 members, no root go.mod root . + ./tools apply --check vex
Linux 1.22.12 fail (build broken, exit 0) not run in sync not_affected
Linux 1.24.7 fail (2×) fail (2×) in sync not_affected
Linux 1.26.8 fail not run in sync not_affected
Linux 1.16 / 1.17 n/a (no go.work before 1.18)
macOS / Windows any not run (probe branches are blocked by stale branches; Windows apply is also blocked by #346)

Vendored (vendor) and hosted modes weren't run this time. Vendored writes a per-member relative ./.socket/vendor/golang/<uuid>/… path, so it very likely conflicts the same way (unverified). Hosted writes a module-path replace (patch.socket.dev/gopatch/<uuid> <sver>), which is identical in both members, so Go should accept it.

First bad version: not a regression. Release 4.0.0 (npm linux-x64-gnu binary) behaves the same as main 61cfb9b.

Suspect code

  • crates/socket-patch-core/src/patch/redirect/golang_local.rs:169 apply_go_redirect → go_mod_edit::ensure_replace_entry (line 304): edits only the --cwd go.mod, with no look at an enclosing go.work or at sibling members' replaces.
  • crates/socket-patch-core/src/patch/redirect/golang_local.rs:452 verify_go_redirect_state (apply --check): checks only the local go.mod and its copy.
  • crates/socket-patch-core/src/vex/discover/golang.rs:103-120: reads only the cwd's go.mod / go.work. A parent go.work and its other members aren't read, so the wiring_conflict gate (crates/socket-patch-cli/src/commands/vex_sources.rs:109) never sees the conflict.
Vorherrschende Sprache
Rust
Sterne
8
Forks
0
Ø Merge
15 Std. 39 Min.
Gemergte PRs (30 T.)
104

Entwicklungsumgebung

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus SocketDev/socket-patch

Alle Issues in SocketDev/socket-patch

Ähnliche Issues

Weitere Issues zu Rust

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.