{"record":{"id":"89072ff08ee440f3","repo":"hashicorp/nomad","slug":"missing-policy-name-89072f","errorCode":null,"errorMessage":"missing policy name","messagePattern":"missing policy name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/sentinel.go","lineNumber":33,"sourceCode":"// SentinelPolicies returns a new handle on the Sentinel policies.\nfunc (c *Client) SentinelPolicies() *SentinelPolicies {\n\treturn &SentinelPolicies{client: c}\n}\n\n// List is used to dump all of the policies.\nfunc (a *SentinelPolicies) List(q *QueryOptions) ([]*SentinelPolicyListStub, *QueryMeta, error) {\n\tvar resp []*SentinelPolicyListStub\n\tqm, err := a.client.query(\"/v1/sentinel/policies\", &resp, q)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\treturn resp, qm, nil\n}\n\n// Upsert is used to create or update a policy\nfunc (a *SentinelPolicies) Upsert(policy *SentinelPolicy, q *WriteOptions) (*WriteMeta, error) {\n\tif policy == nil || policy.Name == \"\" {\n\t\treturn nil, errors.New(\"missing policy name\")\n\t}\n\twm, err := a.client.put(\"/v1/sentinel/policy/\"+policy.Name, policy, nil, q)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn wm, nil\n}\n\n// Delete is used to delete a policy\nfunc (a *SentinelPolicies) Delete(policyName string, q *WriteOptions) (*WriteMeta, error) {\n\tif policyName == \"\" {\n\t\treturn nil, errors.New(\"missing policy name\")\n\t}\n\twm, err := a.client.delete(\"/v1/sentinel/policy/\"+policyName, nil, nil, q)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn wm, nil","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/api/sentinel.go#L15-L51","documentation":"SentinelPolicies.Upsert validates its input before issuing the PUT /v1/sentinel/policy/<name> request. If the policy pointer is nil or the policy's Name field is empty, the client refuses to build a URL path with a blank name and returns this error locally, without any server round-trip.","triggerScenarios":"Calling SentinelPolicies().Upsert(&SentinelPolicy{}, q) with Name unset, or Upsert(nil, q), or constructing a SentinelPolicy by deserializing config where the 'name' key was absent/misspelled.","commonSituations":"Terraform/CLI tooling building Sentinel policies from YAML/HCL where the name field is optional or mistyped; code that upserts a policy parsed from a file whose metadata section failed to parse.","solutions":["Set policy.Name to a non-empty string before calling Upsert.","Validate policy and policy.Name != \"\" at the call site before invoking Upsert.","Check that the source config/JSON actually contains the policy name field with the correct key.","For delete-after-upsert flows, ensure the delete uses the same non-empty name."],"exampleFix":"// before\nclient.SentinelPolicies().Upsert(&SentinelPolicy{Rules: rules}, nil)\n// after\nclient.SentinelPolicies().Upsert(&SentinelPolicy{Name: \"deny-privileged\", Rules: rules}, nil)","handlingStrategy":"validation","validationCode":"func canUpsert(p *api.SentinelPolicy) bool {\n    return p != nil && p.Name != \"\"\n}\nif !canUpsert(policy) { return fmt.Errorf(\"sentinel policy requires a name\") }","typeGuard":"func hasName(p *api.SentinelPolicy) bool {\n    return p != nil && p.Name != \"\"\n}","tryCatchPattern":"if !hasName(policy) {\n    return fmt.Errorf(\"policy.Name must be set before Upsert\")\n}\n_, err := client.SentinelPolicies().Upsert(policy, nil)\nif err != nil { return fmt.Errorf(\"upsert sentinel policy %q: %w\", policy.Name, err) }","preventionTips":["Always populate SentinelPolicy.Name before calling Upsert.","Validate policy structs parsed from config files immediately after decoding.","Add unit tests covering upsert with an empty-name policy.","Wrap upsert calls to return the intended policy name in error messages."],"tags":["validation","sentinel","input-validation","api"],"backgroundTag":"missing-required-argument","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"}