go-module-absolute-path-replace
Problem: go.mod for the main module (github.com/wojons/get-h3 at ~/get-h3) contained replace directives to absolute local paths (~/get-h3/sdk-go, ~/consensus). On a fresh clone those directories don't exist, so every build failed. Reproduced:
main.go:6:2: github.com/wojons/consensus@v0.0.0-00010101000000-000000000000:
replacement directory ~/consensus does not exist
main.go:7:2: github.com/wojons/sdk-go@v0.0.0-00010101000000-000000000000:
replacement directory ~/get-h3/sdk-go does not exist
Fix (two classes of dependency):
1. Published module → pin require to the released tag, DELETE the replace. Before pinning, the local checkout must be verified code-identical to the tag (git diff v0.1.1..HEAD empty — it was). Resulting go.mod:
module github.com/wojons/get-h3
go 1.26
require (
github.com/wojons/consensus v0.0.0-20260808062530-16ca8a9f71ce
github.com/wojons/sdk-go v0.1.1
)
// consensus is unpublished in this org; use the public fork (code-identical).
// The fork's go.mod declares the ORIGINAL module path github.com/wojons/consensus.
replace github.com/wojons/consensus => github.com/totalwindupflightsystems/consensus v0.0.0-20260808062530-16ca8a9f71ce
github.com/wojons/sdk-go → pinned require … v0.1.1; the replace … => ~/get-h3/sdk-go line was deleted (resolved from the module proxy like any published module).github.com/wojons/consensus → unpublished in this org, repo lives under a different org → fork-replace github.com/wojons/consensus => github.com/totalwindupflightsystems/consensus v0.0.0-20260808062530-16ca8a9f71ce. The fork's go.mod declares the original module path (module github.com/wojons/consensus), so all imports of github.com/wojons/consensus keep working. go mod tidy recorded the proxy hashes in go.sum.2. CI clean-checkout-build job (.github/workflows/ci.yml) — actions/setup-go reads the Go version straight from go.mod, and a fresh checkout must build with zero local state:
name: CI
on:
push: { branches: [main] }
pull_request:
jobs:
clean-checkout-build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Go (version from go.mod)
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Build all packages
run: go build ./...
- name: Vet
run: go vet ./...
Environment was empty, so I reconstructed the scenario: local repos `sdk-go` (tag `v0.1.1`) and `consensus`, a broken main repo, and a hermetic **file-based module proxy** (`GOPROXY=file://~/goproxy`, `GOSUMDB=off`) serving exactly the two modules the fixed `go.mod` references — simulating GitHub's proxy for the fictional orgs. `go.sum` integrity is therefore verified for real (zip hashes computed with the same `dirhash.HashZip` algorithm go uses). **Verification (fresh clone, local checkouts hidden, empty module cache):** | # | Check | Result | |---|-------|--------| | 1 | `git clone` of broken commit → `go build` (dirs hidden) | **Fails**: `replacement directory ~/consensus does not exist` | | 2 | `git -C sdk-go diff v0.1.1..HEAD` | **Empty** — HEAD == tag `c0699f9`, so pinning `v0.1.1` is code-identical (asserted in the fix commit) | | 3 | `git clone` of fixed repo → `go build ./...` | **OK** (both modules downloaded from proxy: `wojons/sdk-go@v0.1.1`, `totalwindupflightsystems/consensus@v0.0.0-…`) | | 4 | `go mod verify` in clone | **all modules verified** (go.sum ↔ proxy zips) | | 5 | `go run .` | `hello from sdk-go v0.1.1 | consensus: locked true` | | 6 | `git status --porcelain` after build (default `-mod=readonly`) | **clean** — no go.mod/go.sum drift | | 7 | `grep -r ~` in clone | **none** — no machine-specific paths remain | | 8 | `go vet ./...` | **OK** | | 9 | CI YAML parsed | job `clean-checkout-build`, `go-version-file: go.mod`, `go build ./...` all present | | 10 | Fork `.mod` served by proxy | declares `module github.com/wojons/consensus` (original path) — satisfies the replace requirement | **Edge cases tested:** - **Tampered fork zip** (rebuilt bad checksum): go rejects with `checksum mismatch` / `SECURITY ERROR` — go.sum catches any proxy tampering. - **Fork declaring its own module path instead of the original**: go 1.26 builds it too (empirically the path check for version-replaces isn't enforced), but the problem's requirement — fork `go.mod` must declare the ORIGINAL path — is satisfied and is the correct, portable behavior; the note documents why. - **Fork-replace module identity**: `require github.com/wojons/consensus` + fork-replace resolves imports under the original path; go.sum keys record the downloaded fork path. - **`go mod tidy`** from the broken state was run with only proxy access — it resolves entirely from published/fork modules, no local paths needed.
{"model": "deepseek-v4-flash", "problem_class": "go-module-absolute-path-replace", "result": "passed", "tests": 10}Problem: go.mod for the main module (github.com/wojons/get-h3 at ~/get-h3) contained replace directives to absolute local paths (~/get-h3/sdk-go, ~/consensus). On a fresh clone those directories don't exist, so every build failed. Reproduced:
main.go:6:2: github.com/wojons/consensus@v0.0.0-00010101000000-000000000000:
replacement directory ~/consensus does not exist
main.go:7:2: github.com/wojons/sdk-go@v0.0.0-00010101000000-000000000000:
replacement directory ~/get-h3/sdk-go does not exist
Fix (two classes of dependency):
1. Published module → pin require to the released tag, DELETE the replace. Before pinning, the local checkout must be verified code-identical to the tag (git diff v0.1.1..HEAD empty — it was). Resulting go.mod:
module github.com/wojons/get-h3
go 1.26
require (
github.com/wojons/consensus v0.0.0-20260808062530-16ca8a9f71ce
github.com/wojons/sdk-go v0.1.1
)
// consensus is unpublished in this org; use the public fork (code-identical).
// The fork's go.mod declares the ORIGINAL module path github.com/wojons/consensus.
replace github.com/wojons/consensus => github.com/totalwindupflightsystems/consensus v0.0.0-20260808062530-16ca8a9f71ce
github.com/wojons/sdk-go → pinned require … v0.1.1; the replace … => ~/get-h3/sdk-go line was deleted (resolved from the module proxy like any published module).github.com/wojons/consensus → unpublished in this org, repo lives under a different org → fork-replace github.com/wojons/consensus => github.com/totalwindupflightsystems/consensus v0.0.0-20260808062530-16ca8a9f71ce. The fork's go.mod declares the original module path (module github.com/wojons/consensus), so all imports of github.com/wojons/consensus keep working. go mod tidy recorded the proxy hashes in go.sum.2. CI clean-checkout-build job (.github/workflows/ci.yml) — actions/setup-go reads the Go version straight from go.mod, and a fresh checkout must build with zero local state:
name: CI
on:
push: { branches: [main] }
pull_request:
jobs:
clean-checkout-build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Go (version from go.mod)
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Build all packages
run: go build ./...
- name: Vet
run: go vet ./...
Environment was empty, so I reconstructed the scenario: local repos `sdk-go` (tag `v0.1.1`) and `consensus`, a broken main repo, and a hermetic **file-based module proxy** (`GOPROXY=file://~/goproxy`, `GOSUMDB=off`) serving exactly the two modules the fixed `go.mod` references — simulating GitHub's proxy for the fictional orgs. `go.sum` integrity is therefore verified for real (zip hashes computed with the same `dirhash.HashZip` algorithm go uses). **Verification (fresh clone, local checkouts hidden, empty module cache):** | # | Check | Result | |---|-------|--------| | 1 | `git clone` of broken commit → `go build` (dirs hidden) | **Fails**: `replacement directory ~/consensus does not exist` | | 2 | `git -C sdk-go diff v0.1.1..HEAD` | **Empty** — HEAD == tag `c0699f9`, so pinning `v0.1.1` is code-identical (asserted in the fix commit) | | 3 | `git clone` of fixed repo → `go build ./...` | **OK** (both modules downloaded from proxy: `wojons/sdk-go@v0.1.1`, `totalwindupflightsystems/consensus@v0.0.0-…`) | | 4 | `go mod verify` in clone | **all modules verified** (go.sum ↔ proxy zips) | | 5 | `go run .` | `hello from sdk-go v0.1.1 | consensus: locked true` | | 6 | `git status --porcelain` after build (default `-mod=readonly`) | **clean** — no go.mod/go.sum drift | | 7 | `grep -r ~` in clone | **none** — no machine-specific paths remain | | 8 | `go vet ./...` | **OK** | | 9 | CI YAML parsed | job `clean-checkout-build`, `go-version-file: go.mod`, `go build ./...` all present | | 10 | Fork `.mod` served by proxy | declares `module github.com/wojons/consensus` (original path) — satisfies the replace requirement | **Edge cases tested:** - **Tampered fork zip** (rebuilt bad checksum): go rejects with `checksum mismatch` / `SECURITY ERROR` — go.sum catches any proxy tampering. - **Fork declaring its own module path instead of the original**: go 1.26 builds it too (empirically the path check for version-replaces isn't enforced), but the problem's requirement — fork `go.mod` must declare the ORIGINAL path — is satisfied and is the correct, portable behavior; the note documents why. - **Fork-replace module identity**: `require github.com/wojons/consensus` + fork-replace resolves imports under the original path; go.sum keys record the downloaded fork path. - **`go mod tidy`** from the broken state was run with only proxy access — it resolves entirely from published/fork modules, no local paths needed.
{"model": "deepseek-v4-flash", "problem_class": "go-module-absolute-path-replace", "result": "passed", "tests": 10}