{"record":{"id":"581b972ea7b10868","repo":"gastownhall/beads","slug":"externaldoltconfig-tlscert-tlskey-set-without-tls","errorCode":null,"errorMessage":"ExternalDoltConfig: TLSCert/TLSKey set without TLSRequired","messagePattern":"ExternalDoltConfig: TLSCert/TLSKey set without TLSRequired","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configfile/external_dolt_config.go","lineNumber":85,"sourceCode":"\t\treturn errors.New(\"ExternalDoltConfig: TLSKey set without TLSCert\")\n\t}\n\n\tif c.TLSCert != \"\" && !filepath.IsAbs(c.TLSCert) {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: TLSCert %q is not absolute\", c.TLSCert)\n\t}\n\tif c.TLSKey != \"\" && !filepath.IsAbs(c.TLSKey) {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: TLSKey %q is not absolute\", c.TLSKey)\n\t}\n\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","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/configfile/external_dolt_config.go#L67-L103","documentation":"ExternalDoltConfig.Validate() enforces that TLS material is only supplied when TLSRequired=true. TLSCert and/or TLSKey are client certificate files for mutual TLS; setting them while TLSRequired is false means the config asks for a client cert but then builds no TLS connection at all (TLSClientConfig returns nil when !TLSRequired), so the fields would be silently ignored. This error makes that contradiction a hard startup failure instead.","triggerScenarios":"Any of: constructing ExternalDoltConfig with TLSCert or TLSKey set but TLSRequired omitted/false, then calling Validate() directly or indirectly via buildProxiedServerClientInfo, NewExternalDoltServer, or NewExternalDoltServerUOWProvider. Typically a YAML/env config that sets tls_cert/tls_key (copied from a mTLS setup) but forgets tls_required: true.","commonSituations":"Copying a working mTLS client config from another service but omitting the enable-TLS flag; toggling TLSRequired off during debugging while leaving cert/key paths in place; template/tooling that renders tls_cert and tls_key unconditionally.","solutions":["Set TLSRequired: true in the config if the external Dolt server actually requires TLS/mTLS.","Remove the TLSCert and TLSKey fields if the server really is plaintext-only.","Verify the server's actual TLS requirement (does it listen with --tls?) and align the config before restarting."],"exampleFix":"// before (YAML)\nexternal:\n  host: dolt.internal\n  port: 3307\n  tls_cert: /etc/beads/client-cert.pem\n  tls_key: /etc/beads/client-key.pem\n// after\nexternal:\n  host: dolt.internal\n  port: 3307\n  tls_required: true\n  tls_cert: /etc/beads/client-cert.pem\n  tls_key: /etc/beads/client-key.pem","handlingStrategy":"validation","validationCode":"func validateTLS(cfg configfile.ExternalDoltConfig) error {\n\tif (cfg.TLSCert != \"\" || cfg.TLSKey != \"\") && !cfg.TLSRequired {\n\t\treturn fmt.Errorf(\"tls_cert/tls_key require tls_required: true\")\n\t}\n\treturn cfg.Validate()\n}\n// call before handing the config to NewExternalDoltServer / NewExternalDoltServerUOWProvider","typeGuard":null,"tryCatchPattern":"if err := configfile.ExternalDoltConfig{...}.Validate(); err != nil {\n\tif strings.Contains(err.Error(), \"TLSCert/TLSKey set without TLSRequired\") {\n\t\t// fix config: enable tls_required or drop cert/key, then retry\n\t}\n\treturn err\n}","preventionTips":["Treat TLS fields as one block: never render tls_cert/tls_key in config templates without tls_required.","Run Validate() on config load, before constructing servers, and fail fast with a clear message.","Lint deployed YAML for tls_* keys appearing without tls_required."],"tags":["tls","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"}