{"record":{"id":"5f3fecc3ca9893ee","repo":"hashicorp/nomad","slug":"only-one-storage-block-is-allowed","errorCode":null,"errorMessage":"only one storage block is allowed","messagePattern":"only one storage block is allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/quota_apply.go","lineNumber":332,"sourceCode":"\n\t// Parse per-node-pool limit\n\tif o := listVal.Filter(\"node_pool\"); len(o.Items) > 0 {\n\t\tresult.NodePools = make([]*api.NodePoolLimit, 0)\n\t\tif err := parseNodePoolLimit(&result.NodePools, o); err != nil {\n\t\t\treturn multierror.Prefix(err, \"node pool ->\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc parseStorageResource(storageBlocks *ast.ObjectList) (*api.QuotaStorageResources, error) {\n\tswitch len(storageBlocks.Items) {\n\tcase 0:\n\t\treturn nil, nil\n\tcase 1:\n\tdefault:\n\t\treturn nil, errors.New(\"only one storage block is allowed\")\n\t}\n\tblock := storageBlocks.Items[0]\n\tvalid := []string{\"variables\", \"host_volumes\"}\n\tif err := helper.CheckHCLKeys(block.Val, valid); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar m map[string]any\n\tif err := hcl.DecodeObject(&m, block.Val); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvariablesLimit, err := parseQuotaMegabytes(m[\"variables\"])\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid variables limit: %v\", err)\n\t}\n\thostVolumesLimit, err := parseQuotaMegabytes(m[\"host_volumes\"])\n\tif err != nil {","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/quota_apply.go#L314-L350","documentation":"HCL validation error in parseStorageResource for quota specifications: more than one storage block was declared, but a quota's storage section accepts exactly one block listing variables/host_volumes limits.","triggerScenarios":"Running `nomad quota apply <name> <file.hcl>` where the HCL file contains duplicate `storage { ... }` blocks.","commonSituations":"Merging quota files by concatenation, copy-pasting blocks and forgetting to remove the old one, templating bugs that emit the block twice.","solutions":["Edit the HCL file to keep exactly one storage block, merging keys into it.","Search the file for repeated `storage {` occurrences and deduplicate.","Validate the merged file with `nomad quota apply` on a scratch copy before applying to production."],"exampleFix":"// before\nstorage {\n  variables { enabled = true }\n}\nstorage {\n  host_volumes { enabled = true }\n}\n// after\nstorage {\n  variables     { enabled = true }\n  host_volumes  { enabled = true }\n}","handlingStrategy":"validation","validationCode":"import \"github.com/hashicorp/hcl/v2/hclsimple\"\n// or pre-parse:\nfunc countStorageBlocks(hclSrc string) int {\n    return strings.Count(hclSrc, \"storage {\")\n}\nif countStorageBlocks(src) > 1 {\n    return errors.New(\"quota HCL has more than one storage block\")\n}","typeGuard":null,"tryCatchPattern":"if err := quotaApply(); err != nil && strings.Contains(err.Error(), \"only one storage block is allowed\") {\n    // deduplicate storage blocks in the HCL file and retry\n}","preventionTips":["Grep quota HCL for duplicate `storage {` before applying.","Merge storage settings into a single block when combining files.","Lint quota templates to emit the block exactly once."],"tags":["hcl","quota","config","duplicate-block"],"backgroundTag":"duplicate-config-block","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"}