hashicorp/nomad · error

error parsing: root should be an object

Error message

error parsing: root should be an object

What it means

Returned by parseNamespaceSpec when an HCL namespace spec file (used by `nomad namespace apply` style flows) parses to something other than an *ast.ObjectList at the root. The parser expects the file's top level to be an object of blocks (e.g. `namespace { ... }`); a bare scalar, string, or array at the top level fails this type assertion.

Source

Thrown at command/namespace_apply.go:208

		return 1
	}

	c.Ui.Output(fmt.Sprintf("Successfully applied namespace %q!", namespace.Name))

	return 0
}

// parseNamespaceSpec is used to parse the namespace specification from HCL
func parseNamespaceSpec(input []byte) (*api.Namespace, error) {
	root, err := hcl.ParseBytes(input)
	if err != nil {
		return nil, err
	}

	// Top-level item should be a list
	list, ok := root.Node.(*ast.ObjectList)
	if !ok {
		return nil, fmt.Errorf("error parsing: root should be an object")
	}

	var spec api.Namespace
	if err := parseNamespaceSpecImpl(&spec, list); err != nil {
		return nil, err
	}

	return &spec, nil
}

// parseNamespaceSpec parses the quota namespace taking as input the AST tree
func parseNamespaceSpecImpl(result *api.Namespace, list *ast.ObjectList) error {
	// Decode the full thing into a map[string]interface for ease
	var m map[string]any
	if err := hcl.DecodeObject(&m, list); err != nil {
		return err
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Ensure the file's top level is an object: wrap contents in `namespace { ... }`.
  2. Compare against a known-good spec from `nomad namespace inspect <name>`.
  3. Validate HCL syntax with `hclfmt` or an HCL linter before applying.
  4. Do not feed JSON-formatted specs where HCL object blocks are expected.
  5. Check the file is non-empty and was fully saved/copied.

Example fix

// before: fields floating at top level
name = "prod"
description = "production"
// after
namespace "prod" {
  description = "production"
}
Defensive patterns

Strategy: validation

Validate before calling

// ensure the spec root is an object block before applying
grep -q '^namespace' "$SPEC_FILE" || { echo "$SPEC_FILE must contain a top-level namespace block"; exit 1; }

Type guard

func isObjectList(root *ast.Node) bool {
    _, ok := root.(*ast.ObjectList)
    return ok
}

Try / catch

spec, err := parseNamespaceSpec(path)
if err != nil && strings.Contains(err.Error(), "root should be an object") {
    return fmt.Errorf("%s: wrap contents in a top-level `namespace { ... }` block", path)
}

Prevention

When it happens

Trigger: Feeding `nomad namespace apply` a spec file whose content is not an object — e.g. a JSON array, a quoted string, an empty file that parses oddly, or HCL where the namespace block wrapper was omitted and only fields were pasted at top level in an unexpected shape.

Common situations: Hand-editing an exported namespace spec and accidentally deleting the `namespace { ... }` block wrapper; saving JSON output back as an HCL input; copying a partial snippet instead of the full block; CRLF/encoding oddities leaving only stray tokens.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/0eeebdb9e8181601. Report an issue: GitHub.