gohugoio/hugo · error

npm pack: unsupported workspaces object; missing "packages"

Error message

npm pack: unsupported workspaces object; missing "packages" field

What it means

When ensuring the root package.json references Hugo's autogenerated workspace, Hugo supports `workspaces` either as an array or as the yarn-classic object form `{ "packages": [...] }`. If `workspaces` is an object but has no `packages` key, Hugo cannot know where to insert its workspace path and refuses to guess, failing fast per its no-silent-fallback policy.

Source

Thrown at modules/npm/package_builder.go:272

	quoted := fmt.Sprintf("%q", workspacePath)

	wsVal, hasWS := pkg["workspaces"]

	switch v := wsVal.(type) {
	case []any:
		// Array form: ["pkg-a", "pkg-b", ...]
		if slices.Contains(toStringSlice(v), workspacePath) {
			if runtime.GOOS == "windows" {
				return afero.WriteFile(fsys, packageJSONName, data, 0o666)
			}
			return nil
		}
		// Fall through to byte-based insertion into the existing array below.
	case map[string]any:
		// Object form: { "workspaces": { "packages": [...] } }
		packagesVal, ok := v["packages"]
		if !ok {
			return fmt.Errorf("npm pack: unsupported workspaces object; missing \"packages\" field")
		}
		packagesSlice := toStringSlice(packagesVal)
		if slices.Contains(packagesSlice, workspacePath) {
			if runtime.GOOS == "windows" {
				return afero.WriteFile(fsys, packageJSONName, data, 0o666)
			}
			return nil
		}

		// 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)

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Add a `packages` array to the workspaces object: `"workspaces": { "packages": [] }` — Hugo will then append its workspace path.
  2. Or simplify to the array form: `"workspaces": []`.
  3. Re-run `hugo mod npm pack` after the change.

Example fix

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

Strategy: validation

Validate before calling

var pkg struct{ Workspaces any `json:"workspaces"` }
json.Unmarshal(data, &pkg)
if m, ok := pkg.Workspaces.(map[string]any); ok {
    if _, ok := m["packages"]; !ok {
        return errors.New("workspaces object must contain a \"packages\" array")
    }
}

Type guard

func hasPackagesField(ws any) bool {
    m, ok := ws.(map[string]any)
    if !ok { return false }
    _, ok = m["packages"].([]any)
    return ok
}

Prevention

When it happens

Trigger: `hugo mod npm pack` on a project whose root package.json has `"workspaces": {}` or an object containing only yarn-specific fields like `nohoist` without `packages`.

Common situations: Yarn workspaces configs that use `nohoist` but omitted `packages`; hand-migrated monorepo configs; tooling that wrote an empty workspaces object placeholder.

Related errors


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