hashicorp/nomad · error
error parsing: root should be an object
Error message
error parsing: root should be an object
What it means
`nomad quota apply -parse-only` (and related parsing) reads an HCL quota specification file and expects the top-level AST node to be an ObjectList (the file's body). If the parsed root is not an object (e.g. the file contains a bare scalar, list, or is otherwise malformed), parsing fails with this error.
Source
Thrown at command/quota_apply.go:152
c.Ui.Error(fmt.Sprintf("Error applying quota specification: %s", err))
return 1
}
c.Ui.Output(fmt.Sprintf("Successfully applied quota specification %q!", spec.Name))
return 0
}
// parseQuotaSpec is used to parse the quota specification from HCL
func parseQuotaSpec(input []byte) (*api.QuotaSpec, 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.QuotaSpec
if err := parseQuotaSpecImpl(&spec, list); err != nil {
return nil, err
}
return &spec, nil
}
// parseQuotaSpecImpl parses the quota spec taking as input the AST tree
func parseQuotaSpecImpl(result *api.QuotaSpec, list *ast.ObjectList) error {
// Check for invalid keys
valid := []string{
"name",
"description",
"limit",
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Ensure the quota file's top level is HCL object syntax: `name = "..."` plus `limits { ... }` blocks.
- If the spec is JSON, keep the .json extension so the JSON parser is used.
- Verify the file is non-empty and was not truncated or overwritten.
- Check for characters before the first key (BOM, comments in wrong format) that can make the root parse as non-object.
Example fix
// before (quota.hcl, invalid root)
["team-a"]
// after
name = "team-a"
description = "quota for team a"
limits { region = "global" } Defensive patterns
Strategy: validation
Validate before calling
const content = fs.readFileSync(quotaFile, 'utf8');
if (content.trim() === '') throw new Error('quota file is empty');
if (quotaFile.endsWith('.json') && !content.trim().startsWith('{')) throw new Error('JSON quota must be an object at top level');
if (!quotaFile.endsWith('.json') && !/^[a-zA-Z_]+\s*=/.test(content.trim()) && !/(limits|name)\s*[={]/.test(content)) throw new Error('HCL quota must start with key/value blocks'); Prevention
- Keep JSON quotas in .json files and HCL quotas in .nomad.hcl/.hcl files.
- Run `nomad quota apply -parse-only` in CI before applying quota changes.
- Never leave quota files empty; start with name = "...".
When it happens
Trigger: Passing a quota HCL file whose top level is not key/value blocks — e.g. an empty file, a file containing only a JSON array, or content that HCL parses into a non-object root.
Common situations: Uploading a JSON-encoded quota (which needs the .json extension/JSON parser) with a .hcl name, an accidentally emptied file, or a file with stray syntax that breaks HCL parsing.
Related errors
- limit should be an object
- resource: should be an object
- <combined HCL diagnostics from str.String()>
- Unable to parse job submission to re-enable scaling policies
- only one 'region_limit' block allowed per limit
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/40acbcd3c535132b.
Report an issue: GitHub.