{"record":{"id":"789b0e83eafa22a9","repo":"gastownhall/beads","slug":"externaldoltconfig-tlsrequired-over-socket-needs","errorCode":null,"errorMessage":"ExternalDoltConfig: TLSRequired over Socket needs TLSServerName or TLSSkipVerify","messagePattern":"ExternalDoltConfig: TLSRequired over Socket needs TLSServerName or TLSSkipVerify","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configfile/external_dolt_config.go","lineNumber":94,"sourceCode":"\tif c.TLSCACert != \"\" && !filepath.IsAbs(c.TLSCACert) {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: TLSCACert %q is not absolute\", c.TLSCACert)\n\t}\n\n\tif !c.TLSRequired {\n\t\tswitch {\n\t\tcase c.TLSCACert != \"\":\n\t\t\treturn errors.New(\"ExternalDoltConfig: TLSCACert set without TLSRequired\")\n\t\tcase c.TLSCert != \"\" || c.TLSKey != \"\":\n\t\t\treturn errors.New(\"ExternalDoltConfig: TLSCert/TLSKey set without TLSRequired\")\n\t\tcase c.TLSServerName != \"\":\n\t\t\treturn errors.New(\"ExternalDoltConfig: TLSServerName set without TLSRequired\")\n\t\tcase c.TLSSkipVerify:\n\t\t\treturn errors.New(\"ExternalDoltConfig: TLSSkipVerify set without TLSRequired\")\n\t\t}\n\t}\n\n\tif c.TLSRequired && hasSocket && c.TLSServerName == \"\" && !c.TLSSkipVerify {\n\t\treturn errors.New(\"ExternalDoltConfig: TLSRequired over Socket needs TLSServerName or TLSSkipVerify\")\n\t}\n\n\tif c.KeepAlivePeriod < 0 {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: KeepAlivePeriod %s is negative\", c.KeepAlivePeriod)\n\t}\n\n\treturn nil\n}\n\nfunc (c ExternalDoltConfig) TLSClientConfig() (*tls.Config, error) {\n\tif !c.TLSRequired {\n\t\treturn nil, nil\n\t}\n\n\tcfg := &tls.Config{MinVersion: tls.VersionTLS12}\n\n\tif c.TLSSkipVerify {\n\t\tcfg.InsecureSkipVerify = true //nolint:gosec // G402: opt-in insecure transport via the TLSSkipVerify testing flag","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/configfile/external_dolt_config.go#L76-L112","documentation":"When TLSRequired is set and the connection uses a Unix Socket, there is no hostname to use for TLS server-name verification, so the config must supply either TLSServerName (explicit SNI name) or TLSSkipVerify (explicit opt-out). Without one, certificate verification over a socket is impossible and the validator fails the config rather than producing a TLS client that can never verify the peer.","triggerScenarios":"Constructing ExternalDoltConfig with Socket set to an absolute path plus TLSRequired=true, but leaving TLSServerName empty and TLSSkipVerify false; Validate() (or NewExternalDoltServer / buildProxiedServerClientInfo / NewExternalDoltServerUOWProvider) rejects the combination.","commonSituations":"Migrating a TCP+TLS config to a local socket connection (e.g. sidecar deployment) and keeping tls_required: true; enabling TLS on a socket-based external Dolt server without realizing sockets have no hostname for cert verification.","solutions":["Add TLSServerName set to the name in the server certificate (correct fix).","Set TLSSkipVerify: true for local/test sockets where verification is impractical (insecure; avoid in production).","Switch back to Host/Port transport if the remote server's certificate should be verified against its real hostname."],"exampleFix":"// before (YAML)\nexternal:\n  socket: /run/dolt/dolt.sock\n  tls_required: true\n// after\nexternal:\n  socket: /run/dolt/dolt.sock\n  tls_required: true\n  tls_server_name: dolt.local\n  tls_ca_cert: /etc/beads/ca.pem","handlingStrategy":"validation","validationCode":"func validateSocketTLS(cfg configfile.ExternalDoltConfig) error {\n\tif cfg.Socket != \"\" && cfg.TLSRequired && cfg.TLSServerName == \"\" && !cfg.TLSSkipVerify {\n\t\treturn fmt.Errorf(\"TLS over socket %q needs tls_server_name or tls_skip_verify\", cfg.Socket)\n\t}\n\treturn cfg.Validate()\n}","typeGuard":null,"tryCatchPattern":"if err := cfg.Validate(); err != nil {\n\tif strings.Contains(err.Error(), \"TLSRequired over Socket needs\") {\n\t\t// add tls_server_name (or tls_skip_verify for local dev), then retry\n\t}\n\treturn err\n}","preventionTips":["When switching a TLS config from Host/Port to Socket, always carry over or set TLSServerName.","Prefer Host/Port + CA cert verification for production; reserve socket+skip-verify for local dev.","Run Validate() in a startup preflight so the failure occurs before any connection attempt."],"tags":["tls","unix-socket","config-validation","external-dolt"],"backgroundTag":"tls-config-mismatch","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}