{"record":{"id":"ac7e560530c36bd2","repo":"hashicorp/nomad","slug":"error-parsing-root-should-be-an-object-ac7e56","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/var_put.go","lineNumber":480,"sourceCode":"\t\tout.CreateTime = 0\n\t\tout.ModifyIndex = 0\n\t\tout.ModifyTime = 0\n\t}\n\treturn out, nil\n}\n\n// parseVariableSpec is used to parse the variable specification\n// from HCL\nfunc parseVariableSpec(input []byte, verbose func(string)) (*api.Variable, error) {\n\troot, err := hcl.ParseBytes(input)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Top-level item should be a list\n\tlist, ok := root.Node.(*ast.ObjectList)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"error parsing: root should be an object\")\n\t}\n\n\tvar out api.Variable\n\tif err := parseVariableSpecImpl(&out, list); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &out, nil\n}\n\n// parseVariableSpecImpl parses the variable taking as input the AST tree\nfunc parseVariableSpecImpl(result *api.Variable, list *ast.ObjectList) error {\n\t// Decode the full thing into a map[string]interface for ease\n\tvar m map[string]any\n\tif err := hcl.DecodeObject(&m, list); err != nil {\n\t\treturn err\n\t}\n\n\t// Check for invalid keys","sourceCodeStart":462,"sourceCodeEnd":498,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/var_put.go#L462-L498","documentation":"parseVariableSpec parses HCL input for `var put` and expects the top-level node to be an ObjectList (an HCL object). If the parsed root is anything else (e.g. the file is JSON, or contains only scalar/list values), the parser returns the fixed message `error parsing: root should be an object`.","triggerScenarios":"Feeding `nomad var put -in=hcl` a file whose top level is not an HCL object — for example a bare JSON document (JSON object lists do not come through as *ast.ObjectList in this parser), a file containing only a list or a bare string, or an empty file.","commonSituations":"Mixing up -in flags: passing JSON content with -in=hcl; a spec file that starts with comments only; writing an HCL file with top-level array syntax `[...]` instead of blocks/assignments.","solutions":["Check the file actually contains HCL object syntax at top level (key = value or block {}), not JSON or a bare list.","If the content is JSON, rerun with `-in=json`.","Regenerate a valid template with `nomad var init` and port your values into it.","Ensure the file is not empty or comment-only."],"exampleFix":"// before (JSON passed as HCL)\n{ \"path\": \"app/config\" }\n// after (HCL form)\npath = \"app/config\"\nitems { key = \"value\" }","handlingStrategy":"validation","validationCode":"// pre-parse and confirm the HCL root is an object before invoking the command\nf, _ := hcl.ParseBytes(data)\nif _, ok := f.Node.(*hclast.ObjectList); !ok {\n    return errors.New(\"HCL spec root must be an object (key = value / blocks)\")\n}","typeGuard":"func isHCLObjectRoot(data []byte) bool {\n    root, err := hcl.ParseBytes(data)\n    if err != nil { return false }\n    _, ok := root.Node.(*hclast.ObjectList)\n    return ok\n}","tryCatchPattern":"if err := run(); err != nil && strings.Contains(err.Error(), \"root should be an object\") {\n    log.Fatal(\"you likely passed JSON content with -in=hcl; switch flags or convert the file\")\n}","preventionTips":["Match file extension and content format, and set -in explicitly.","Use HCL block/key=value syntax at top level, never JSON braces.","Regenerate specs from `nomad var init` rather than converting formats by hand."],"tags":["hcl","cli","nomad","parsing","schema"],"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"}