gohugoio/hugo · error

npm pack: unsupported workspaces type %T

Error message

npm pack: unsupported workspaces type %T

What it means

The `workspaces` field in the root package.json may be an array, an object with `packages`, or null/absent. Any other JSON type — a string, number, or boolean — is invalid per npm's schema, and Hugo rejects it with the concrete Go type (%T) rather than guessing an interpretation.

Source

Thrown at modules/npm/package_builder.go:299

		// Append the new workspace path to the packages slice.
		newPkgs := make([]any, 0, len(packagesSlice)+1)
		for _, s := range packagesSlice {
			newPkgs = append(newPkgs, s)
		}
		newPkgs = append(newPkgs, workspacePath)
		v["packages"] = newPkgs

		updated, err := json.MarshalIndent(pkg, "", indent)
		if err != nil {
			return fmt.Errorf("npm pack: failed to marshal package.json with updated workspaces: %w", err)
		}
		updated = append(updated, '\n')
		return afero.WriteFile(fsys, packageJSONName, updated, 0o666)
	case nil:
		// Treat explicit null as "no workspaces"; handled below as missing key.
	default:
		return fmt.Errorf("npm pack: unsupported workspaces type %T", v)
	}

	// Try adding to existing workspaces array when present.
	if hasWS && wsVal != nil {
		if wsIdx := bytes.Index(data, []byte(`"workspaces"`)); wsIdx >= 0 {
			rest := data[wsIdx:]
			if bracketOpen := bytes.IndexByte(rest, '['); bracketOpen >= 0 {
				if bracketClose := bytes.IndexByte(rest[bracketOpen:], ']'); bracketClose >= 0 {
					pos := wsIdx + bracketOpen + bracketClose
					arrayContent := bytes.TrimSpace(data[wsIdx+bracketOpen+1 : pos])
					var insertion string
					if len(arrayContent) == 0 {
						insertion = "\n" + indent + indent + quoted + "\n" + indent
					} else {
						insertion = ",\n" + indent + indent + quoted + "\n" + indent
					}
					result := make([]byte, 0, len(data)+len(insertion))
					result = append(result, data[:pos]...)

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Wrap the value in an array: `"workspaces": ["packages/*"]`.
  2. If you intended the yarn object form, use `"workspaces": { "packages": ["packages/*"] }`.
  3. Validate against npm's package.json schema before re-running `hugo mod npm pack`.

Example fix

// before
{ "workspaces": "packages/*" }
// after
{ "workspaces": ["packages/*"] }
Defensive patterns

Strategy: type-guard

Validate before calling

switch ws := pkg["workspaces"].(type) {
case []any, map[string]any, nil:
    // supported
default:
    return fmt.Errorf("workspaces must be an array or object, got %T", ws)
}

Type guard

func isValidWorkspaces(v any) bool {
    switch v.(type) {
    case nil, []any, map[string]any:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: `hugo mod npm pack` reading a root package.json where `workspaces` is e.g. `"packages/*"` (a bare string), `true`, or a number — anything other than []any, map[string]any, or null.

Common situations: Writing `"workspaces": "packages/*"` instead of an array (a frequent hand-editing mistake); a templating/codegen step emitting the wrong type; copying a glob from docs without the surrounding brackets.

Related errors


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