hashicorp/nomad · error
exposed service check %s->%s->%s requires use of sidecar_pro
Error message
exposed service check %s->%s->%s requires use of sidecar_proxy
What it means
Nomad's job validation rejects a group service check with expose=true when the service's Connect block has no sidecar_proxy. Exposed checks only work by routing through the Envoy sidecar that Consul Connect injects; without connect { sidecar_service {} } there is no proxy to bind the exposed listener in, so the job is invalid. HasSidecar() is simply `c != nil && c.SidecarService != nil` (nomad/structs/services.go:1286).
Source
Thrown at nomad/job_endpoint_hook_expose_check.go:109
s.Connect.SidecarService.Proxy.Expose = new(structs.ConsulExposeConfig)
}
return s.Connect.SidecarService.Proxy.Expose
}
// containsExposePath returns true if path is contained in paths.
func containsExposePath(paths []structs.ConsulExposePath, path structs.ConsulExposePath) bool {
return slices.Contains(paths, path)
}
// tgValidateUseOfCheckExpose ensures that any service check in tg making use
// of the expose field is within an appropriate context to do so. The check must
// be a group level check, and must use the builtin envoy proxy.
func tgValidateUseOfCheckExpose(tg *structs.TaskGroup) error {
// validation for group services (which must use built-in connect proxy)
for _, s := range tg.Services {
for _, check := range s.Checks {
if check.Expose && !s.Connect.HasSidecar() {
return fmt.Errorf(
"exposed service check %s->%s->%s requires use of sidecar_proxy",
tg.Name, s.Name, check.Name,
)
}
}
}
// validation for task services (which must not be configured to use Expose)
for _, t := range tg.Tasks {
for _, s := range t.Services {
for _, check := range s.Checks {
if check.Expose {
return fmt.Errorf(
"exposed service check %s[%s]->%s->%s is not a task-group service",
tg.Name, t.Name, s.Name, check.Name,
)
}
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Add connect { sidecar_service {} } to the group service so Envoy is injected.
- Remove expose = true from the check if you don't need it exposed through the proxy.
- Move the service to group level if it is currently a task service (task services can never use expose; see error 2346).
Example fix
// before
service {
name = "api"
connect {}
check {
expose = true
}
}
// after
service {
name = "api"
connect { sidecar_service {} }
check {
expose = true
}
} Defensive patterns
Strategy: validation
Validate before calling
// Pre-check HCL/JSON job spec before submit
tg.Services.each { s ->
s.Checks.each { c ->
if c.Expose && !(s.Connect != null && s.Connect.SidecarService != null)
throw new Error("check '${c.Name}' on service '${s.Name}' sets expose but service has no sidecar_proxy")
}
} Type guard
func hasConnectSidecar(s *api.Service) bool {
return s != nil && s.Connect != nil && s.Connect.SidecarService != nil
} Try / catch
// golang
err := client.Jobs().Validate(job)
if err != nil && strings.Contains(err.Error(), "requires use of sidecar_proxy") {
// amend job spec: add connect.sidecar_service
} Prevention
- Always pair expose = true with connect { sidecar_service {} } in the same service block.
- Lint job specs with nomad job validate before submit in CI.
- Remember expose is group-service-only; keep exposed checks at group level.
- Keep the sidecar proxy resource stanza when copying expose examples.
When it happens
Trigger: Submitting (nomad job run / jobs API Validate) a job where a task-group-level service has a check with expose=true but the service's connect block is absent, or is connect { sidecar_service { ... } } missing, or uses connect native.
Common situations: Copy-pasting an expose example onto a service that only has connect {} without sidecar_service; assuming expose works with connect-native services; upgrading an HCL file where the sidecar block was removed but checks kept expose = true.
Related errors
- exposed service check %s[%s]->%s->%s is not a task-group ser
- ErrConnectRequireOneNetwork
- ErrConnectInvalidNetworkMode
- service.port must be set for mesh gateway service
- %s: %w: group %q has %d networks
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/35783f2a3f8d5163.
Report an issue: GitHub.