{"record":{"id":"7bd22296d6a041c7","repo":"hashicorp/nomad","slug":"failed-to-set-up-tls-expiration-metrics-w","errorCode":null,"errorMessage":"failed to set up TLS expiration metrics: %w","messagePattern":"failed to set up TLS expiration metrics: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/agent.go","lineNumber":188,"sourceCode":"\t\treturn nil, err\n\t}\n\tif err := a.setupClient(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif err := a.setupEnterpriseAgent(logger); err != nil {\n\t\treturn nil, err\n\t}\n\tif a.client == nil && a.server == nil {\n\t\treturn nil, fmt.Errorf(\"must have at least client or server mode enabled\")\n\t}\n\n\t// If the agent is configured with TLS, set up the TLS metrics process to\n\t// emit certificate expiry metrics and start this.\n\tif !a.config.TLSConfig.IsEmpty() {\n\t\ttlsMetrics, err := newTLSMetrics(a.logger, a.config.TLSConfig, nil)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to set up TLS expiration metrics: %w\", err)\n\t\t}\n\t\ta.tlsMetrics = tlsMetrics\n\t\ttlsMetrics.start(a.config.Telemetry.collectionInterval)\n\t}\n\n\treturn a, nil\n}\n\n// convertServerConfig takes an agent config and log output and returns a Nomad\n// Config. There may be missing fields that must be set by the agent. To do this\n// call finalizeServerConfig.\nfunc convertServerConfig(agentConfig *Config) (*nomad.Config, error) {\n\tconf := agentConfig.NomadConfig\n\tif conf == nil {\n\t\tconf = nomad.DefaultConfig()\n\t}\n\tconf.DevMode = agentConfig.DevMode\n\tconf.EnableDebug = agentConfig.EnableDebug","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/agent.go#L170-L206","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the wrapped cause (%w) to find the real failure (file not found, permission denied, parse error).","Verify all TLS cert/key/CA paths in the config exist and are readable by the nomad process.","If TLS metrics are not needed, ensure the TLS config is fully empty so the metrics setup is skipped.","Fix cert provisioning/ordering (e.g. mount secrets before agent start)."],"exampleFix":"// before\nagent {\n  tls {}\n}\n// after\nagent {\n  tls {\n    http = true\n    cert_file = \"/etc/nomad/tls/nomad.pem\"\n    key_file  = \"/etc/nomad/tls/nomad-key.pem\"\n    ca_file   = \"/etc/nomad/tls/ca.pem\"\n  }\n}","handlingStrategy":"try-catch","validationCode":"// Go: pre-check TLS files before startup\nfunc checkTLS(tlsCfg *config.TLSConfig) error {\n    if tlsCfg == nil || tlsCfg.IsEmpty() { return nil }\n    for _, p := range []string{tlsCfg.CertFile, tlsCfg.KeyFile, tlsCfg.CAFile} {\n        if p == \"\" { continue }\n        if _, err := os.Stat(p); err != nil {\n            return fmt.Errorf(\"tls file %q unreadable: %w\", p, err)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"a, err := agent.NewAgent(cfg, logger)\nif err != nil {\n    var wrappedErr error\n    if strings.Contains(err.Error(), \"failed to set up TLS expiration metrics\") {\n        wrappedErr = err // inspect with %v / errors.Unwrap for the root cause\n    }\n    return fmt.Errorf(\"agent startup failed: %w\", err)\n}","preventionTips":["Provision TLS certs before starting the agent (init containers, systemd ordering, vault-agent prestart).","Verify cert/key/CA paths exist and are readable by the nomad user as part of startup health checks.","Use tlsstanza validation tooling (e.g. openssl x509 -in cert) in CI for rendered configs."],"tags":["nomad","tls","config","startup"],"backgroundTag":"tls-certificate-load-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}