hashicorp/nomad · error
service %q contains invalid check: agent checks do not suppo
Error message
service %q contains invalid check: agent checks do not support scripts
What it means
Nomad's Consul client builds agent-side service registrations by looping over each check on a service. Script checks (check.Type == structs.ServiceCheckScript) require the Nomad task driver to execute, but agent services are registered directly with the local Consul agent, which has no Nomad task context to run a script. The code therefore rejects the whole service registration with this error instead of registering a check Consul cannot run.
Source
Thrown at command/agent/consul/service_client.go:1261
// older agents use SHA-1 hashes as part of the service name instead of
// SHA-256, but we can't guarantee they've shutdown gracefully and
// deregistered themselves on upgrade. Remove any legacy service IDs
// that might be lingering
//
// COMPAT: remove once upgrades from pre-FIPS-compatible agents are no longer
// supported. Upgrading agents in-place to FIPS-enabled is unsupported.
legacyID := service.LegacyAgentID(role)
if legacyID != "" {
// we intentionally swallow this error because these services likely
// no longer exist
_ = c.agentAPI.ServiceDeregisterOpts(legacyID, nil)
}
for _, check := range service.Checks {
checkID := MakeCheckID(id, check)
if check.Type == structs.ServiceCheckScript {
return fmt.Errorf("service %q contains invalid check: agent checks do not support scripts", service.Name)
}
checkHost, checkPort := serviceReg.Address, serviceReg.Port
if check.PortLabel != "" {
// Unlike tasks, agents don't use port labels. Agent ports are
// stored directly in the PortLabel.
host, rawport, err := net.SplitHostPort(check.PortLabel)
if err != nil {
return fmt.Errorf("error parsing port label %q from check %q: %v", service.PortLabel, check.Name, err)
}
port, err := strconv.Atoi(rawport)
if err != nil {
return fmt.Errorf("error parsing port %q from check %q: %v", rawport, check.Name, err)
}
checkHost, checkPort = host, port
}
checkReg, err := createCheckReg(id, checkID, check, checkHost, checkPort, "")
if err != nil {
return fmt.Errorf("failed to add check %q: %v", check.Name, err)View on GitHub (pinned to 482b49bf1a)
Solutions
- Remove the script check or change its type to 'http' or 'tcp' for agent services (agent checks only support http/tcp/grpc-style non-script checks)
- If script execution is required, move the service and check into a job's task group (task-level service registration) instead of agent config
- Verify with `consul services` / agent logs which check carried type script and fix the source config block
- Upgrade/align Nomad versions if a Nomad-generated agent check unexpectedly contains a script type
Example fix
// before (agent client config HCL)
check {
type = "script"
command = "/usr/local/bin/health.sh"
interval = "10s"
timeout = "2s"
}
// after
check {
type = "http"
path = "/v1/agent/health"
interval = "10s"
timeout = "2s"
} Defensive patterns
Strategy: validation
Validate before calling
// Before writing agent service config, assert check types
for _, c := range service.Checks {
if c.Type == structs.ServiceCheckScript {
return fmt.Errorf("agent service %q cannot use script checks; use http/tcp", service.Name)
}
} Try / catch
// if registering programmatically
if err := client.RegisterAgentWorkload(w); err != nil {
if strings.Contains(err.Error(), "do not support scripts") {
// strip script checks and retry with http/tcp fallback
}
} Prevention
- Only use script checks in task-level service blocks, never agent config
- Add a config linter that rejects type="script" in agent/client service stanzas
- Prefer http checks against the Nomad agent's own /v1/agent/health endpoint
- Review Nomad version release notes for agent check type support
When it happens
Trigger: Calling agent service registration (serviceClient.RegisterAgentWorkload, invoked when an agent registers its own services like 'Nomad Client' HTTP/RPC services or via client config) with a check whose Type is 'script'. Happens when agent config or a client 'check' block sets check type to script, or a driver-network/agent path passes a templated check that resolved to a script type.
Common situations: Copying a task-level check block with `type = "script"` into the Nomad agent's client config; a version upgrade where check types are derived differently; misconfigured check_template producing a script check on an agent service.
Related errors
- error parsing port label %q from service %q: %v
- error parsing port %q from service %q: %v
- invalid name %q, must match regex %s
- invalid initial check state (%s), must be one of %q, %q, %q
- error creating bootstrap configuration for Connect proxy sid
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/4e440e7668f46149.
Report an issue: GitHub.