gohugoio/hugo · error
verifying @ : checksum mismatch: !=
Error message
verifying %s@%s: checksum mismatch: %s != %s
What it means
Hugo maintains its own hugo.direct.sum file recording content hashes of modules it directly manages. During writeHugoDirectSum it compares freshly-computed sums against the stored ones and aborts if a path@version's hash changed — a guard against silent content drift under a pinned version. The mismatch shows the new vs stored hash.
Solutions
- If the change is intentional (you edited the module), delete the stale sum file: `rm _vendor/hugo.direct.sum` or the project's hugo.direct.sum and rebuild so it regenerates.
- For local replace development, prefer editing then `hugo mod tidy` so sums refresh.
- If the module was re-published under the same tag (bad upstream practice), `go clean -modcache && hugo mod clean` to force a clean re-download.
- If hugo.direct.sum is checked into git and conflicting, commit the updated sum or remove it from version control.
Example fix
// before: checksum mismatch blocks build // after: let Hugo regenerate the direct sum file rm -f hugo.direct.sum _vendor/hugo.direct.sum hugo
Defensive patterns
Strategy: validation
Validate before calling
// Before building, drop a stale direct sum if the module tree was edited
func refreshDirectSumIfDirty(repoRoot string) error {
sum := filepath.Join(repoRoot, "hugo.direct.sum")
if _, err := os.Stat(sum); err == nil {
// let hugo regenerate it rather than trust a stale hash
return os.Remove(sum)
}
return nil
} Type guard
null
Try / catch
null
Prevention
- During local module development, remove hugo.direct.sum after edits.
- Do not check a stale hugo.direct.sum into git across module re-publishes.
- Treat re-published tags as broken; pin a fresh version.
- Use `hugo mod tidy` after modifying replaced modules.
When it happens
Trigger: A module whose on-disk content changed while its declared path@version stayed identical — e.g. a local replace edited after first build, a force-pushed git tag re-downloaded into a dirty cache, or a hand-edited module dir. writeHugoDirectSum runs at the end of module collection.
Common situations: Developing a theme via local replace and editing files, CI caching a module across a re-publish of the same tag, a re-pulled module whose dependency changed, or a stale hugo.direct.sum checked into git that conflicts with the current tree.
Related errors
- not found
- failed to apply mounts for project
- failed to decode module download result
- failed to decode modules list
- failed to download module
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/4f11829b4ae7b0db.
Report an issue: GitHub.
Appendix: source
Thrown at modules/client.go:636
sums = append(sums, modSum{pathVersionKey: pathVersionKey{path: m.Path(), version: m.Version()}, sum: m.Sum()})
}
}
// Read the existing sums.
existingSums, err := c.readModSumFile(hugoDirectSumFilename)
if err != nil {
return err
}
if len(sums) == 0 && len(existingSums) == 0 {
// Nothing to do.
return nil
}
dirty := len(sums) != len(existingSums)
for _, s1 := range sums {
if s2, ok := existingSums[s1.pathVersionKey]; ok {
if s1.sum != s2 {
return fmt.Errorf("verifying %s@%s: checksum mismatch: %s != %s", s1.path, s1.version, s1.sum, s2)
}
} else if !dirty {
dirty = true
}
}
if !dirty {
// Nothing changed.
return nil
}
// Write the sums file.
// First sort the sums for reproducible output.
sort.Slice(sums, func(i, j int) bool {
pvi, pvj := sums[i].pathVersionKey, sums[j].pathVersionKey
return pvi.path < pvj.path || (pvi.path == pvj.path && pvi.version < pvj.version)
})
f, err := c.fs.OpenFile(filepath.Join(c.ccfg.WorkingDir, hugoDirectSumFilename), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o666)View on GitHub (pinned to 52c9bd7908)