{"record":{"id":"d0da605ab718f106","repo":"hashicorp/nomad","slug":"service-s-in-s-has-an-identity-with-an-empty-nam","errorCode":null,"errorMessage":"Service %s in %s has an identity with an empty name","messagePattern":"Service (.+?) in (.+?) has an identity with an empty name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/job_endpoint_hooks.go","lineNumber":571,"sourceCode":"\n\treturn warnings, validationErrors.ErrorOrNil()\n}\n\nfunc (v *jobValidate) isEligibleForMultiIdentity() bool {\n\tif v.srv == nil || v.srv.serf == nil {\n\t\treturn true // handle tests w/o real servers safely\n\t}\n\treturn v.srv.peersCache.ServersMeetMinimumVersion(\n\t\tv.srv.Region(), minVersionMultiIdentities, true)\n}\n\nfunc (v *jobValidate) validateServiceIdentity(s *structs.Service, parent string, okForIdentity bool) error {\n\tif s.Identity != nil && !okForIdentity {\n\t\treturn fmt.Errorf(\"Service %s in %s cannot have an identity until all servers are upgraded to %s or later\",\n\t\t\ts.Name, parent, minVersionMultiIdentities)\n\t}\n\tif s.Identity != nil && s.Identity.Name == \"\" {\n\t\treturn fmt.Errorf(\"Service %s in %s has an identity with an empty name\", s.Name, parent)\n\t}\n\n\treturn nil\n}\n\n// validateVaultIdentity validates that a task is properly configured to access\n// a Vault cluster.\n//\n// It assumes the jobImplicitIdentitiesHook mutator hook has been called to\n// inject task identities if necessary.\nfunc (v *jobValidate) validateVaultIdentity(t *structs.Task, okForIdentity bool) ([]error, error) {\n\tvar warnings []error\n\n\tif t.Vault == nil {\n\t\t// Warn if task doesn't use Vault but has Vault identities.\n\t\tfor _, wid := range t.Identities {\n\t\t\tif strings.HasPrefix(wid.Name, structs.WorkloadIdentityVaultPrefix) {\n\t\t\t\twarnings = append(warnings, fmt.Errorf(\"Task %s has an identity called %s but no vault block\", t.Name, wid.Name))","sourceCodeStart":553,"sourceCodeEnd":589,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/job_endpoint_hooks.go#L553-L589","documentation":"Fires in validateServiceIdentity when a service's identity block has an empty name; workload identities require a concrete identity name to derive the token path and variables.","triggerScenarios":"Submitting a job with a service whose identity is non-nil but whose identity.name is the empty string.","commonSituations":"Half-converted job specs where identity {} was added but name left blank; templating that renders an empty name variable; hand-written HCL missing the required attribute.","solutions":["Set identity.name explicitly, e.g. identity { name = \"consul-service-<service>\" }","Remove the empty identity block if service identities are not actually needed"],"exampleFix":"// before\nservice { name = \"web\" identity { } }\n// after\nservice { name = \"web\" identity { name = \"consul-service-web\" } }","handlingStrategy":"validation","validationCode":"for _, svc := range group.Services {\n\tif svc.Identity != nil && svc.Identity.Name == \"\" {\n\t\treturn fmt.Errorf(\"service %s identity.name required\", svc.Name)\n\t}\n}","typeGuard":"func identityNamed(w *api.WorkloadIdentity) bool { return w != nil && w.Name != \"\" }","tryCatchPattern":null,"preventionTips":["Always set identity.name following the consul-service-<name> convention","Lint job specs for empty required attributes"],"tags":["nomad","workload-identity","consul","job-spec"],"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"}