hashicorp/nomad · error

failed to set up TLS expiration metrics: %w

Error message

failed to set up TLS expiration metrics: %w

What it means

When the agent config includes a TLS section, NewAgent creates a TLS metrics worker (newTLSMetrics) that emits certificate expiry metrics. If constructing that worker fails, the agent aborts startup and wraps the underlying error with this message.

Source

Thrown at command/agent/agent.go:188

		return nil, err
	}
	if err := a.setupClient(); err != nil {
		return nil, err
	}

	if err := a.setupEnterpriseAgent(logger); err != nil {
		return nil, err
	}
	if a.client == nil && a.server == nil {
		return nil, fmt.Errorf("must have at least client or server mode enabled")
	}

	// If the agent is configured with TLS, set up the TLS metrics process to
	// emit certificate expiry metrics and start this.
	if !a.config.TLSConfig.IsEmpty() {
		tlsMetrics, err := newTLSMetrics(a.logger, a.config.TLSConfig, nil)
		if err != nil {
			return nil, fmt.Errorf("failed to set up TLS expiration metrics: %w", err)
		}
		a.tlsMetrics = tlsMetrics
		tlsMetrics.start(a.config.Telemetry.collectionInterval)
	}

	return a, nil
}

// convertServerConfig takes an agent config and log output and returns a Nomad
// Config. There may be missing fields that must be set by the agent. To do this
// call finalizeServerConfig.
func convertServerConfig(agentConfig *Config) (*nomad.Config, error) {
	conf := agentConfig.NomadConfig
	if conf == nil {
		conf = nomad.DefaultConfig()
	}
	conf.DevMode = agentConfig.DevMode
	conf.EnableDebug = agentConfig.EnableDebug

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Read the wrapped cause (%w) to find the real failure (file not found, permission denied, parse error).
  2. Verify all TLS cert/key/CA paths in the config exist and are readable by the nomad process.
  3. If TLS metrics are not needed, ensure the TLS config is fully empty so the metrics setup is skipped.
  4. Fix cert provisioning/ordering (e.g. mount secrets before agent start).

Example fix

// before
agent {
  tls {}
}
// after
agent {
  tls {
    http = true
    cert_file = "/etc/nomad/tls/nomad.pem"
    key_file  = "/etc/nomad/tls/nomad-key.pem"
    ca_file   = "/etc/nomad/tls/ca.pem"
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: pre-check TLS files before startup
func checkTLS(tlsCfg *config.TLSConfig) error {
    if tlsCfg == nil || tlsCfg.IsEmpty() { return nil }
    for _, p := range []string{tlsCfg.CertFile, tlsCfg.KeyFile, tlsCfg.CAFile} {
        if p == "" { continue }
        if _, err := os.Stat(p); err != nil {
            return fmt.Errorf("tls file %q unreadable: %w", p, err)
        }
    }
    return nil
}

Try / catch

a, err := agent.NewAgent(cfg, logger)
if err != nil {
    var wrappedErr error
    if strings.Contains(err.Error(), "failed to set up TLS expiration metrics") {
        wrappedErr = err // inspect with %v / errors.Unwrap for the root cause
    }
    return fmt.Errorf("agent startup failed: %w", err)
}

Prevention

When it happens

Trigger: newTLSMetrics returning an error during NewAgent because a.config.TLSConfig is non-empty but invalid — e.g. unparseable cert paths, missing/unreadable certificate files, or malformed TLS config for the metrics emitter.

Common situations: Typo in cert_file/key_file/ca_file paths; certificate files not present on disk at agent start (mounted secret not ready); TLS stanza enabled in config but certs never provisioned.

Understand the failure class

Related errors


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