hashicorp/nomad · error
failed to generate envoy bootstrap config
Error message
failed to generate envoy bootstrap config: %w
What it means
The envoy_bootstrap_hook generates the Envoy bootstrap configuration for a Connect sidecar/gateway during Prestart. It first loads the Consul SI (service identity) token with maybeLoadSIToken; if that fails, it logs an error and returns 'failed to generate envoy bootstrap config' wrapping the cause. Without the SI token the bootstrap file cannot be generated correctly.
Solutions
- Check the wrapped error to see if the token file is missing vs unreadable
- Ensure the task has a Consul service identity (consul.token / workload identity) configured
- Verify Consul is >= 1.8 and ACLs are enabled/compatible with SI token flow
- Confirm the task's SecretsDir exists and is populated before Prestart completes
- Retry the allocation; the hook regenerates the bootstrap on restart
Example fix
// before: no identity configured for the connect service
service { name = "api" connect { sidecar_service {} } } // missing token
// after: ensure Consul SI token is provisioned to the task
// enable Consul SI token injection (Consul >=1.8, acls enabled) or supply
// identity { kind = "consul"; name = "api" } in the task group Defensive patterns
Strategy: validation
Validate before calling
// before Prestart, verify the SI token artifact is present
if _, err := os.Stat(filepath.Join(secretsDir, consulTokenFilename)); err != nil {
return fmt.Errorf("consul SI token missing for envoy bootstrap: %w", err)
} Try / catch
if err := hook.Prestart(req); err != nil {
if strings.Contains(err.Error(), "failed to generate envoy bootstrap config") {
log.Printf("envoy bootstrap failed: %v; check Consul SI token provisioning", err)
}
return err
} Prevention
- Provision Consul SI tokens (identity blocks) for every Connect task
- Run Consul >= 1.8 with ACLs enabled for the SI token flow
- Verify SecretsDir is mounted and populated before envoy hooks run
- Test Connect services after Consul/Consul upgrades
When it happens
Trigger: maybeLoadSIToken returns an error: the consul token file is missing from the task's SecretsDir when Connect requires it, unreadable permissions, or an error reading/writing the token path inside the secrets directory.
Common situations: Task running Consul Connect services without the Consul SI identity/Token configured; Consul version too old to support SI tokens; secrets dir not mounted or cleaned before the hook runs; Consul ACL setup incomplete.
Related errors
- envoy must be used as connect sidecar or gateway
- error creating bootstrap configuration for Connect proxy…
- error interpreting desired Envoy version from Consul
- error retrieving supported Envoy versions from Consul
- invalid Consul Connect configuration for service
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/015548821acab383.
Report an issue: GitHub.
Appendix: source
Thrown at client/allocrunner/taskrunner/envoy_bootstrap_hook.go:307
// Set runtime environment variables for the envoy admin and ready listeners.
resp.Env = map[string]string{
helper.CleanEnvVar(envoyAdminBindEnvPrefix+serviceName, '_'): envoyAdminBind,
helper.CleanEnvVar(envoyReadyBindEnvPrefix+serviceName, '_'): envoyReadyBind,
}
// Envoy bootstrap configuration may contain a Consul token, so write
// it to the secrets directory like Vault tokens.
bootstrapFilePath := filepath.Join(req.TaskDir.SecretsDir, "envoy_bootstrap.json")
// Write everything related to the command to enable debugging
bootstrapStderrPath := filepath.Join(req.TaskDir.LogDir, "envoy_bootstrap.stderr.0")
bootstrapEnvPath := filepath.Join(req.TaskDir.SecretsDir, ".envoy_bootstrap.env")
bootstrapCmdPath := filepath.Join(req.TaskDir.SecretsDir, ".envoy_bootstrap.cmd")
siToken, err := h.maybeLoadSIToken(req.Task.Name, req.TaskDir.SecretsDir)
if err != nil {
h.logger.Error("failed to generate envoy bootstrap config", "sidecar_for", service.Name)
return fmt.Errorf("failed to generate envoy bootstrap config: %w", err)
}
h.logger.Debug("check for SI token for task", "task", req.Task.Name, "exists", siToken != "")
proxyID := h.proxyServiceID(h.alloc.TaskGroup, service)
bootstrap := h.newEnvoyBootstrapArgs(service, grpcAddr, envoyAdminBind, envoyReadyBind, siToken, bootstrapFilePath, proxyID)
// Create command line arguments
bootstrapArgs := bootstrap.args()
// Write args to file for debugging
argsFile, err := os.Create(bootstrapCmdPath)
if err != nil {
return fmt.Errorf("failed to write bootstrap command line: %w", err)
}
defer argsFile.Close()
if _, err := io.WriteString(argsFile, strings.Join(bootstrapArgs, " ")+"\n"); err != nil {
return fmt.Errorf("failed to encode bootstrap command line: %w", err)
}View on GitHub (pinned to 482b49bf1a)