{"record":{"id":"eaa85c9ef575f6df","repo":"gohugoio/hugo","slug":"failed-to-decode-module-download-result-w","errorCode":null,"errorMessage":"failed to decode module download result: %w","messagePattern":"failed to decode module download result: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/client.go","lineNumber":473,"sourceCode":"\t// No valid cache, need to query.\n\targs := []string{\"mod\", \"download\", \"-json\", fmt.Sprintf(\"%s@%s\", path, version)}\n\n\tb := &bytes.Buffer{}\n\terr := c.runGo(context.Background(), b, args...)\n\tif err != nil {\n\t\t// The -json flag makes Go output error details as JSON to stdout\n\t\t// even on failure. Try to extract the error message from the JSON output.\n\t\tif jsonErr := extractGoModDownloadError(b.Bytes()); jsonErr != \"\" {\n\t\t\treturn nil, fmt.Errorf(\"failed to download module %s@%s: %s: %s\", path, version, err, jsonErr)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"failed to download module %s@%s: %w\", path, version, err)\n\t}\n\n\tjsonResult := b.Bytes()\n\n\tm := &goModule{}\n\tif err := json.NewDecoder(bytes.NewReader(jsonResult)).Decode(m); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode module download result: %w\", err)\n\t}\n\n\tif m.Error != nil {\n\t\treturn nil, errors.New(m.Error.Err)\n\t}\n\n\t// Cache the successful result if it has a Dir field.\n\tif m.Dir != \"\" {\n\t\t_ = c.ccfg.ModuleQueriesCache.SetBytes(cacheKey, jsonResult)\n\t}\n\n\treturn m, nil\n}\n\n// isDirNonEmpty returns true if dir exists and contains at least one file or subdirectory.\nfunc (c *Client) isDirNonEmpty(dir string) bool {\n\tf, err := c.fs.Open(dir)\n\tif err != nil {","sourceCodeStart":455,"sourceCodeEnd":491,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/modules/client.go#L455-L491","documentation":"Raised after `go mod download -json` reportedly succeeded (exit 0) but json.NewDecoder could not unmarshal its stdout into the goModule struct. The data Go wrote is not the shape Hugo expects, so the result is unusable. This is almost always a toolchain/output-format skew, not a user config problem.","triggerScenarios":"downloadModuleVersion receives non-empty stdout that fails struct decode — e.g. a newer Go emitting additional/renamed fields that break strict decoding, stdout contaminated by a wrapper (gimme, asdf, proxy) prepending logs, or a partial/truncated buffer due to a killed process.","commonSituations":"Go version far ahead/behind the Hugo release (field mismatches), shell rc files printing output when `go` is invoked, containerised Hugo where stdout is teed to a logger, or a corrupted module cache producing garbled cached JSON.","solutions":["Confirm the Go binary matches what this Hugo build supports: `go version` and compare against the Hugo release notes for your version.","Run `go mod download -json path@version` manually and inspect whether stdout is clean JSON (no stray log lines).","Clear caches: `go clean -modcache && hugo mod clean` then rebuild to rule out cache corruption.","If a Go wrapper (asdf/gimme) injects output, invoke Hugo with a direct Go binary on PATH."],"exampleFix":"// verify clean JSON output\ngo mod download -json github.com/x/y@v1.2.3 | head\n// if extra log lines appear, fix the Go wrapper/shell rc, then:\nhugo mod clean && hugo","handlingStrategy":"validation","validationCode":"// Confirm go emits clean, decodable JSON for this module\nimport (\"encoding/json\"; \"os/exec\")\n\nfunc validateDownloadJSON(path, version string) error {\n  out, err := exec.Command(\"go\", \"mod\", \"download\", \"-json\", path+\"@\"+version).Output()\n  if err != nil { return err }\n  var m struct{ Dir, Path, Version string }\n  return json.Unmarshal(out, &m)\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Use the Go version paired with your Hugo release.","Never let version managers inject stdout during go calls.","Treat module-cache corruption as a reason to `go clean -modcache`."],"tags":["modules","go-toolchain","json","hugo-module"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}