{"record":{"id":"102ac72ae9a0b2ae","repo":"hashicorp/nomad","slug":"error-parsing-root-should-be-an-object-102ac7","errorCode":null,"errorMessage":"error parsing: root should be an object","messagePattern":"error parsing: root should be an object","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/volume_create_host.go","lineNumber":216,"sourceCode":"\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif vol.State == api.HostVolumeStateReady {\n\t\t\tc.Ui.Info(fmt.Sprintf(\"==> %s: Volume %q ready\",\n\t\t\t\tformatTime(time.Now()), limit(vol.Name, opts.length)))\n\t\t\treturn nil\n\t\t}\n\t}\n}\n\nfunc decodeHostVolume(input *ast.File) (*api.HostVolume, error) {\n\tvar err error\n\tvol := &api.HostVolume{}\n\n\tlist, ok := input.Node.(*ast.ObjectList)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"error parsing: root should be an object\")\n\t}\n\n\t// Decode the full thing into a map[string]interface for ease\n\tvar m map[string]any\n\terr = hcl.DecodeObject(&m, list)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Need to manually parse these fields/blocks\n\tdelete(m, \"capability\")\n\tdelete(m, \"constraint\")\n\tdelete(m, \"capacity\")\n\tdelete(m, \"capacity_max\")\n\tdelete(m, \"capacity_min\")\n\tdelete(m, \"type\")\n\n\t// Decode the rest","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/volume_create_host.go#L198-L234","documentation":"decodeHostVolume expects the parsed HCL input file to be an ObjectList (i.e. the top level of the HCL body is made of key/value blocks or attributes). When hclparse yields an *ast.File whose Node is not an *ast.ObjectList — for example an empty document or a bare literal — the command refuses to decode it and returns this error instead of panicking on the type assertion.","triggerScenarios":"Calling `nomad volume create` (hostVolumeCreate/hostVolumeRegister) with an HCL volume spec whose root is not an object: an empty file, a file containing only a bare string/number, or non-HCL content that still parses (e.g. a JSON array at top level).","commonSituations":"Accidentally passing a YAML or JSON list file to the volume command; pointing the -volume flag at an empty file; copy/paste errors that drop all top-level keys; invoking the command with a path whose contents are binary or a lockfile.","solutions":["Ensure the HCL file has at least one top-level `key = value` or `block { ... }` construct so the root parses as an object","Verify the file path passed to the volume create command points to an HCL host-volume spec, not a job file, JSON array, or empty file","Add a top-level attribute (e.g. `name = \"...\"`, `type = \"host\"`) to the spec","Run `hclfmt` or the Nomad job validate/inspect equivalents to sanity-check the file parses to an object"],"exampleFix":"// before (empty or literal-only file)\n\"my-volume\"\n\n// after (proper HCL object root)\nname = \"my-volume\"\ntype = \"host\"\ncapacity = \"10GiB\"\nhost_volume = \"shared-csi-host-volume\"","handlingStrategy":"validation","validationCode":"func looksLikeHCLObject(input string) error {\n\tparsed, err := hcl.Parse(input)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif _, ok := parsed.Node.(*ast.ObjectList); !ok {\n\t\treturn fmt.Errorf(\"volume spec root must be an HCL object (key = value / block { ... }), got %T\", parsed.Node)\n\t}\n\treturn nil\n}\n// call before handing the file to `nomad volume create`","typeGuard":"func isObjectList(f *ast.File) bool {\n\t_, ok := f.Node.(*ast.ObjectList)\n\treturn ok\n}","tryCatchPattern":"vol, err := decodeHostVolume(input)\nif err != nil {\n\tif strings.Contains(err.Error(), \"root should be an object\") {\n\t\treturn fmt.Errorf(\"volume file %s is empty or not an HCL object; check the file contents\", path)\n\t}\n\treturn err\n}","preventionTips":["Always include at least one top-level attribute or block in the volume spec","Verify the file path before invoking the volume command (non-empty, text, HCL)","Never pass JSON arrays or YAML to the HCL volume loader","Lint specs with hclfmt in CI"],"tags":["hcl","parsing","nomad","config"],"backgroundTag":"hcl-root-not-object","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}