{"record":{"id":"aa93b7b037c7006a","repo":"hashicorp/nomad","slug":"consul-ingress-service-requires-a-name","errorCode":null,"errorMessage":"Consul Ingress Service requires a name","messagePattern":"Consul Ingress Service requires a name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/services.go","lineNumber":2421,"sourceCode":"\t}\n\n\tif !pointer.Eq(s.MaxConcurrentRequests, o.MaxConcurrentRequests) {\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nfunc (s *ConsulIngressService) Validate(protocol string) error {\n\tif s == nil {\n\t\treturn nil\n\t}\n\n\t// pre-validate service Name and Hosts before passing along to consul:\n\t// https://developer.hashicorp.com/consul/docs/connect/config-entries/ingress-gateway#services\n\n\tif s.Name == \"\" {\n\t\treturn errors.New(\"Consul Ingress Service requires a name\")\n\t}\n\n\tswitch protocol {\n\tcase \"tcp\":\n\t\tif s.Name == \"*\" {\n\t\t\treturn errors.New(`Consul Ingress Service doesn't support wildcard name for \"tcp\" protocol`)\n\t\t}\n\n\t\tif len(s.Hosts) != 0 {\n\t\t\treturn errors.New(`Consul Ingress Service doesn't support associating hosts to a service for the \"tcp\" protocol`)\n\t\t}\n\tdefault:\n\t\tif s.Name == \"*\" && len(s.Hosts) != 0 {\n\t\t\treturn errors.New(`Consul Ingress Service with a wildcard \"*\" service name can not also specify hosts`)\n\t\t}\n\t}\n\n\treturn nil","sourceCodeStart":2403,"sourceCodeEnd":2439,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/services.go#L2403-L2439","documentation":"Ingress gateway service entries are pre-validated before being sent to Consul. Consul requires each ingress service entry to have a name, so an empty s.Name fails validation in nomad/structs/services.go.","triggerScenarios":"Defining a connect { gateway { ingress {} } } listener service with an omitted/empty name and submitting the job for validation.","commonSituations":"Hand-writing ingress gateway stanzas and forgetting the name field; generating ingress configs programmatically where the name defaults to empty.","solutions":["Set a name on the ingress service entry (a real service name or \"*\" for a catch-all)","Check Terraform/job templating so the name variable is not rendered empty"],"exampleFix":"// before\nlistener {\n  port     = 8080\n  protocol = \"http\"\n  services { }\n}\n// after\nlistener {\n  port     = 8080\n  protocol = \"http\"\n  services { name = \"web\" }\n}","handlingStrategy":"validation","validationCode":"function validateIngressServiceNames(gateway) {\n  for (const l of gateway.listeners ?? []) {\n    for (const s of l.services ?? []) {\n      if (!s.name) throw new Error(`ingress service on port ${l.port} requires a name`);\n    }\n  }\n}","typeGuard":"function hasIngressName(s) { return typeof s.name === \"string\" && s.name.length > 0; }","tryCatchPattern":"try {\n  await nomad.jobs.validate(job);\n} catch (e) {\n  if (e.message === \"Consul Ingress Service requires a name\") {\n    console.error(\"Add a name (or '*') to every ingress service entry\");\n  } else throw e;\n}","preventionTips":["Always include name in ingress services blocks, even for single-service listeners","Assert templated name variables are non-empty before rendering","Run nomad job validate in CI"],"tags":["nomad","consul","ingress-gateway","job-validation"],"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"}