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 ofView on GitHub (pinned to b6b368adc5)
Solutions
- Unwrap the inner error to find the root cause (most often 1076 -> serialize commands).
- Ensure the module directory is writable and not locked by AV / IDE.
- Free disk space / inode quota if write failed due to ENOSPC.
- 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
- Keep go.mod writable (0644) and not held by AV/IDE locks.
- Serialize go commands that touch go.mod.
- Free disk/inodes so writes succeed.
- Read the wrapped inner error before retrying; never retry unchanged.
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
- existing contents have changed since last read
- inode for file changed since last Lock or RLock
- ${GoModToolVersion} is required for tool directives in go.mo
- updates to go.mod needed, but go.mod is part of the overlay
- disallowed module version
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/47dfa204420394e0.
Report an issue: GitHub.