Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

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

Đang mở
#531 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
52/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
go, rust
Lĩnh vực
build-system, cli, tooling

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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.
Ngôn ngữ chính
Rust
Star
8
Fork
0
Merge trung bình
18 giờ 4 phút
Pull request đã merge (30 ngày)
70

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của SocketDev/socket-patch

Tất cả issue của SocketDev/socket-patch

Issue tương tự

Thêm issue về Rust

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.