golang/go · error
zip for %s has unexpected file %s
Error message
zip for %s has unexpected file %s
What it means
When the go command verifies a cached module zip it requires every entry name to begin with `{module.Path}@{module.Version}/`. Any entry missing that prefix is reported as 'unexpected file' — a guard against cache poisoning and malformed archives that has the module-hash check downstream.
Source
Thrown at src/cmd/go/internal/modfetch/fetch.go:344
if err != nil {
return err
}
// Double-check that the paths within the zip file are well-formed.
//
// TODO(bcmills): There is a similar check within the Unzip function. Can we eliminate one?
fi, err := file.Stat()
if err != nil {
return err
}
z, err := zip.NewReader(file, fi.Size())
if err != nil {
return err
}
prefix := mod.Path + "@" + mod.Version + "/"
for _, zf := range z.File {
if !strings.HasPrefix(zf.Name, prefix) {
return fmt.Errorf("zip for %s has unexpected file %s", prefix[:len(prefix)-1], zf.Name)
}
}
if err := file.Close(); err != nil {
return err
}
// Hash the zip file and check the sum before renaming to the final location.
if err := hashZip(f, mod, file.Name(), ziphashfile); err != nil {
return err
}
if err := os.Rename(file.Name(), zipfile); err != nil {
return err
}
// TODO(bcmills): Should we make the .zip and .ziphash files read-only to discourage tampering?
return nilView on GitHub (pinned to b6b368adc5)
Solutions
- Run go clean -modcache to wipe and rebuild the cache from scratch.
- Verify GOMODACHE is not shared with non-Go tooling that writes into it.
- Re-run go mod download for the specific module to repopulate just that entry.
Example fix
// before: cache contains stray top-level files // terminal // go clean -modcache // go mod download
Defensive patterns
Strategy: validation
Validate before calling
// Confirm cache integrity before relying on it.
// go mod verify
// In code, validate the prefix invariant on any cached zip you open:
func cacheZipPrefixOK(mod module.Version, names []string) error {
prefix := mod.Path + "@" + mod.Version + "/"
for _, n := range names {
if !strings.HasPrefix(n, prefix) {
return fmt.Errorf("unexpected entry %q", n)
}
}
return nil
} Prevention
- Run `go mod verify` in CI to catch cache corruption early.
- Never let non-Go tooling write into GOMODCACHE.
- Use go clean -modcache after interrupted downloads.
When it happens
Trigger: fetch.go opens the cached zip, iterates z.File, and finds an entry whose Name does not have the module@version/ prefix. A hand-edited cache, a partial write, or a proxy returning the wrong module triggers it.
Common situations: Stale or partially-written cache after an interrupted download; manual edits to GOMODCACHE; mismatched GOFLAGS/-insecure; disk corruption.
Related errors
- %s %s: missing ziphash: %v
- %s %s: %v
- %s %s: zip has been modified (%v)
- %s %s: dir has been modified (%v)
- gocacheverify=1
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/6fe35e894a91f3cd.
Report an issue: GitHub.