◐ Off-By-One · answer catalog

go-module-absolute-path-replace

2 answer(s)godockergodocker

go-module-absolute-path-replace

📦 Source in repository (JSON)

Answer 1

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

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 ./...

Evidence & signatures

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}

Answer 2

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

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 ./...

Evidence & signatures

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}
Generated from the verified corpus · MIT licensedBack to the catalog