{"record":{"id":"d8bcef3a8d0e1189","repo":"hashicorp/nomad","slug":"verifyincoming-set-and-no-ca-certificate-provided","errorCode":null,"errorMessage":"VerifyIncoming set, and no CA certificate provided!","messagePattern":"VerifyIncoming set, and no CA certificate provided!","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/tlsutil/config.go","lineNumber":369,"sourceCode":"\t// Parse the CA cert if any\n\terr := c.AppendCA(tlsConfig.ClientCAs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Add cert/key\n\tcert, err := c.LoadKeyPair()\n\tif err != nil {\n\t\treturn nil, err\n\t} else if cert != nil {\n\t\ttlsConfig.GetCertificate = c.KeyLoader.GetOutgoingCertificate\n\t}\n\n\t// Check if we require verification\n\tif c.VerifyIncoming {\n\t\ttlsConfig.ClientAuth = tls.RequireAndVerifyClientCert\n\t\tif c.CAFile == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"VerifyIncoming set, and no CA certificate provided!\")\n\t\t}\n\t\tif cert == nil {\n\t\t\treturn nil, fmt.Errorf(\"VerifyIncoming set, and no Cert/Key pair provided!\")\n\t\t}\n\t}\n\n\treturn tlsConfig, nil\n}\n\n// ParseCiphers parses ciphersuites from the comma-separated string into\n// recognized slice\nfunc ParseCiphers(tlsConfig *config.TLSConfig) ([]uint16, error) {\n\tsuites := []uint16{}\n\n\tcipherStr := strings.TrimSpace(tlsConfig.TLSCipherSuites)\n\n\tvar parsedCiphers []string\n\tif cipherStr == \"\" {","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/tlsutil/config.go#L351-L387","documentation":"IncomingTLSConfig builds the tls.Config for inbound connections. With VerifyIncoming set, the server requires and verifies client certificates, which needs a CA to validate against; if CAFile is empty the config is rejected. The CA must be present before a client certificate check can succeed.","triggerScenarios":"Calling IncomingTLSConfig (via startTLSServer / NewTLSConfiguration) with VerifyIncoming=true and CAFile==\"\".","commonSituations":"Setting verify_incoming = true in the tls stanza without ca_file; copying a config where the CA path was removed; Ansible/Helm charts enabling mTLS without mounting the CA secret.","solutions":["Set ca_file in the tls stanza to the CA bundle used to sign client certificates.","If you don't intend to verify client certs, disable verify_incoming.","Verify the CA file path resolves on the server node and contains the signing CA."],"exampleFix":"// before\ncfg := &tlsutil.Config{ VerifyIncoming: true, CertFile: \"cert.pem\", KeyFile: \"key.pem\" }\n// after\ncfg := &tlsutil.Config{ VerifyIncoming: true, CAFile: \"ca.pem\", CertFile: \"cert.pem\", KeyFile: \"key.pem\" }","handlingStrategy":"validation","validationCode":"if cfg.VerifyIncoming && cfg.CAFile == \"\" {\n    return errors.New(\"verify_incoming requires ca_file to be set\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Bundle CA distribution with enabling mTLS flags.","Verify CA file presence/readability at deploy time.","Keep a single source-of-truth tls stanza shared across nodes."],"tags":["tls","mtls","configuration"],"backgroundTag":"tls-verify-incoming-missing-ca","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"}