gohugoio/hugo · error

invalid modules list: %q

Error message

invalid modules list: %q

What it means

When reading a vendor manifest (`_vendor/modules.txt`) in modules/collect.go:625, each non-empty line must have exactly two fields: `# <modulepath> <version>`. A line that trims to anything else fails parsing and Hugo aborts with `invalid modules list: %q`, naming the file. This protects against corrupted or hand-edited vendor metadata silently producing a wrong module set.

Source

Thrown at modules/collect.go:625

		return err
	}

	defer f.Close()

	scanner := bufio.NewScanner(f)

	for scanner.Scan() {
		// # github.com/alecthomas/chroma v0.6.3
		line := scanner.Text()
		line = strings.Trim(line, "# ")
		line = strings.TrimSpace(line)
		if line == "" {
			continue
		}
		parts := strings.Fields(line)
		if len(parts) != 2 {
			return fmt.Errorf("invalid modules list: %q", filename)
		}
		path := parts[0]

		shouldAdd := c.Client.moduleConfig.VendorClosest

		if !shouldAdd {
			if _, found := c.vendored[path]; !found {
				shouldAdd = true
			}
		}

		if shouldAdd {
			c.vendored[path] = vendoredModule{
				Owner:   owner,
				Dir:     filepath.Join(vendorDir, path),
				Version: parts[1],
			}
		}

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Regenerate the vendor tree: delete `_vendor` (or fix modules.txt) and run `hugo mod vendor`.
  2. Open the named modules.txt and remove malformed lines/conflict markers — each line must be `# path version`.
  3. Resolve any git merge conflicts in `_vendor` by re-vendoring rather than hand-merging.
  4. Avoid manual edits to `_vendor/modules.txt`; treat it as generated output.

Example fix

# before (_vendor/modules.txt)
# github.com/alecthomas/chroma
<<<<<<< HEAD
# after: regenerate
rm -rf _vendor
hugo mod vendor
Defensive patterns

Strategy: validation

Validate before calling

switch v := cfg.Get("module.imports").(type) {
case []interface{}, []map[string]interface{}:
    // ok
default:
    return fmt.Errorf("module.imports must be a list, got %T", v)
}

Type guard

func isImportsList(v interface{}) bool {
    _, ok := v.([]interface{})
    return ok
}

Prevention

When it happens

Trigger: `collector` parsing `_vendor/modules.txt` during collection when any line has fewer or more than two whitespace-separated fields after stripping the `# ` prefix — e.g. a module path with no version, extra tokens, or merge-conflict markers.

Common situations: Git merge conflicts leaving `<<<<<<<` markers inside `_vendor/modules.txt`; manual edits to the vendor manifest; line corruption from CRLF/encoding mangling; concatenated files from bad scripts.

Related errors


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