hashicorp/nomad · error

%w: %v; see: <https://developer.hashicorp.com/nomad/s/envoy-

Error message

%w: %v; see: <https://developer.hashicorp.com/nomad/s/envoy-bootstrap-error>

What it means

After the backoff.Retry loop exhausts all attempts to run `consul envoy bootstrap`, the hook wraps the last cmdErr with errEnvoyBootstrapError and a link to the Nomad docs. It is a recoverable error when the failure was an exec.ExitError (non-zero exit from the consul binary), so the task will be restarted and Prestart retried.

Source

Thrown at client/allocrunner/taskrunner/envoy_bootstrap_hook.go:413

		}

		// Command failed, prepare for retry
		//
		// Cleanup the bootstrap file. An errors here is not
		// important as (a) we test to ensure the deletion
		// occurs, and (b) the file will either be rewritten on
		// retry or eventually garbage collected if the task
		// fails.
		_ = os.Remove(bootstrapFilePath)

		return true, cmdErr
	}, backoffOpts)

	if backoffErr != nil {
		// Wrap the last error from Consul and set that as our status.
		_, recoverable := cmdErr.(*exec.ExitError)
		return structs.NewRecoverableError(
			fmt.Errorf("%w: %v; see: <https://developer.hashicorp.com/nomad/s/envoy-bootstrap-error>",
				errEnvoyBootstrapError,
				cmdErr,
			),
			recoverable,
		)
	}

	return nil
}

func (h *envoyBootstrapHook) groupEnv() []string {
	return []string{
		fmt.Sprintf("%s=%s", taskenv.AllocID, h.alloc.ID),
		fmt.Sprintf("%s=%s", taskenv.ShortAllocID, h.alloc.ID[:8]),
		fmt.Sprintf("%s=%s", taskenv.AllocName, h.alloc.Name),
		fmt.Sprintf("%s=%s", taskenv.GroupName, h.alloc.TaskGroup),
		fmt.Sprintf("%s=%s", taskenv.JobName, h.alloc.Job.Name),
		fmt.Sprintf("%s=%s", taskenv.JobID, h.alloc.Job.ID),

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Open the referenced https://developer.hashicorp.com/nomad/s/envoy-bootstrap-error page and the alloc/logs/envoy_bootstrap.stderr.N file for the underlying consul error.
  2. Verify the Consul agent is running and reachable from the Nomad client.
  3. Confirm the `consul` binary exists and is in PATH for the task driver environment.
  4. Check Consul ACL token permissions (service:register, mesh ops) and service stanza correctness.
  5. If recoverable, Nomad restarts the task automatically; fix the underlying Consul issue to stop the restart loop.
Defensive patterns

Strategy: retry

Validate before calling

// preflight before starting connect tasks
if _, err := exec.LookPath("consul"); err != nil { return fmt.Errorf("consul binary missing: %w", err) }
if err := consulAgentReachable(); err != nil { return fmt.Errorf("consul agent unreachable: %w", err) }

Type guard

func isEnvoyBootstrapError(err error) bool {
    return errors.Is(err, errEnvoyBootstrapError)
}

Try / catch

err := hook.Prestart(ctx, req)
if errors.Is(err, errEnvoyBootstrapError) {
    // read alloc/logs/envoy_bootstrap.stderr.N for the real consul failure
    var rec *structs.RecoverableError
    if errors.As(err, &rec) && rec.IsRecoverable() { /* retry with backoff */ }
}

Prevention

When it happens

Trigger: All backoff attempts of cmd.Run() for `consul envoy bootstrap` fail in Prestart — e.g. the consul binary is missing (exec.ErrNotFound), exits non-zero (bad config, unreachable Consul agent), or the context is cancelled repeatedly.

Common situations: Consul agent not running or unreachable on the client; consul binary absent from PATH inside the task environment; invalid service/connect configuration (missing sidecar service, wrong namespace/ACLs); Consul ACL token lacking permissions to register the proxy.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/71cf578e77e99341. Report an issue: GitHub.