golang/go · error

updating go.mod: %w

Error message

updating go.mod: %w

What it means

Generic wrapper emitted when the committed go.mod update transaction failed for any reason other than errNoChange. The original error (commonly error 1076, but also lock failures, I/O write errors) is wrapped with %w under 'updating go.mod:'. This is the user-facing top of the update error chain.

Source

Thrown at src/cmd/go/internal/modload/init.go:2099

			// other process.
			return nil, errNoChange
		}

		if index != nil && !bytes.Equal(old, index.data) {
			// The contents of the go.mod file have changed. In theory we could add all
			// of the new modules to the build list, recompute, and check whether any
			// module in *our* build list got bumped to a different version, but that's
			// a lot of work for marginal benefit. Instead, fail the command: if users
			// want to run concurrent commands, they need to start with a complete,
			// consistent module definition.
			return nil, fmt.Errorf("existing contents have changed since last read")
		}

		return updatedGoMod, nil
	})

	if err != nil && err != errNoChange {
		return fmt.Errorf("updating go.mod: %w", err)
	}
	return nil
}

// keepSums returns the set of modules (and go.mod file entries) for which
// checksums would be needed in order to reload the same set of packages
// loaded by the most recent call to LoadPackages or ImportFromFiles,
// including any go.mod files needed to reconstruct the MVS result
// or identify go versions,
// in addition to the checksums for every module in keepMods.
func keepSums(ld *Loader, ctx context.Context, pld *packageLoader, rs *Requirements, which whichSums) map[module.Version]bool {
	// Every module in the full module graph contributes its requirements,
	// so in order to ensure that the build list itself is reproducible,
	// we need sums for every go.mod in the graph (regardless of whether
	// that version is selected).
	keep := make(map[module.Version]bool)

	// Add entries for modules in the build list with paths that are prefixes of

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Unwrap the inner error to find the root cause (most often 1076 -> serialize commands).
  2. Ensure the module directory is writable and not locked by AV / IDE.
  3. Free disk space / inode quota if write failed due to ENOSPC.
  4. Re-run after resolving the root cause; the transaction is atomic so no partial write remains.

Example fix

// before
$ go build ./...
// updating go.mod: existing contents have changed since last read

// after (resolve the inner cause)
$ pkill -f 'go mod'   // stop the concurrent writer
$ go build ./...
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure go.mod is writable and not locked before building.
fi, err := os.Stat("go.mod")
if err != nil { return err }
if fi.Mode().Perm()&0200 == 0 {
    return errors.New("go.mod not writable; updates will fail")
}
// also ensure no other writer holds it (advisory lock check omitted for brevity)

Try / catch

out, err := exec.Command("go", "build", "./...").CombinedOutput()
if err != nil && bytes.Contains(out, []byte("updating go.mod:")) {
    // unwrap inner cause to route recovery
    inner := strings.TrimSpace(strings.TrimPrefix(string(out), "updating go.mod:"))
    switch {
    case strings.Contains(inner, "existing contents have changed"):
        // serialize and retry once
        out, err = exec.Command("go", "build", "./...").CombinedOutput()
    case strings.Contains(inner, "permission denied"):
        return fmt.Errorf("go.mod not writable: %s", inner)
    default:
        return fmt.Errorf("go.mod update failed: %s", inner)
    }
}
return err

Prevention

When it happens

Trigger: modload commits the go.mod rewrite closure and the returned err is non-nil and not errNoChange. Most often the inner error is 'existing contents have changed since last read' (1076); can also be fsync/write permission errors.

Common situations: Same as 1076 plus read-only filesystems, full disk, antivirus locking go.mod on Windows, or a held lock by another process.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/47dfa204420394e0. Report an issue: GitHub.