gohugoio/hugo · error

failed to decode module download result: %w

Error message

failed to decode module download result: %w

What it means

Returned when `go mod download -json` succeeded (exit 0) but the JSON it wrote to stdout could not be decoded into Hugo's goModule struct. It signals corrupted or unexpected output from the Go toolchain rather than a download failure per se.

Source

Thrown at modules/client.go:473

	// No valid cache, need to query.
	args := []string{"mod", "download", "-json", fmt.Sprintf("%s@%s", path, version)}

	b := &bytes.Buffer{}
	err := c.runGo(context.Background(), b, args...)
	if err != nil {
		// The -json flag makes Go output error details as JSON to stdout
		// even on failure. Try to extract the error message from the JSON output.
		if jsonErr := extractGoModDownloadError(b.Bytes()); jsonErr != "" {
			return nil, fmt.Errorf("failed to download module %s@%s: %s: %s", path, version, err, jsonErr)
		}
		return nil, fmt.Errorf("failed to download module %s@%s: %w", path, version, err)
	}

	jsonResult := b.Bytes()

	m := &goModule{}
	if err := json.NewDecoder(bytes.NewReader(jsonResult)).Decode(m); err != nil {
		return nil, fmt.Errorf("failed to decode module download result: %w", err)
	}

	if m.Error != nil {
		return nil, errors.New(m.Error.Err)
	}

	// Cache the successful result if it has a Dir field.
	if m.Dir != "" {
		_ = c.ccfg.ModuleQueriesCache.SetBytes(cacheKey, jsonResult)
	}

	return m, nil
}

// isDirNonEmpty returns true if dir exists and contains at least one file or subdirectory.
func (c *Client) isDirNonEmpty(dir string) bool {
	f, err := c.fs.Open(dir)
	if err != nil {

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Run `go mod download -json <path>@<version>` manually and inspect the raw output.
  2. Remove wrappers/aliases around the go binary that print extra output.
  3. Unset GOFLAGS/GODEBUG values that alter go command output.
  4. Upgrade Hugo and Go to compatible recent versions.
Defensive patterns

Strategy: try-catch

Type guard

func isDecodeErr(err error) bool {
    var syntaxErr *json.SyntaxError
    var typeErr *json.UnmarshalTypeError
    return errors.As(err, &syntaxErr) || errors.As(err, &typeErr)
}

Try / catch

if err := client.Download(mods); err != nil {
    if isDecodeErr(err) {
        // go tool output was malformed — likely go version mismatch or GOFLAGS polluting stdout
        return fmt.Errorf("unexpected 'go mod download -json' output; check Go version compatibility: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: json.Decoder failing on `go mod download -json` output: non-JSON noise interleaved on stdout (wrappers, GODEBUG output), a truncated buffer, or a Go version emitting an incompatible format.

Common situations: Shell wrappers or scripts around the `go` binary that print to stdout, GOFLAGS injecting flags that change output, or very new/old Go releases changing the -json schema.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/eaa85c9ef575f6df.json. Report an issue: GitHub ↗.