{"record":{"id":"b18419e92ecd63c3","repo":"gastownhall/beads","slug":"externaldoltconfig-tlscert-q-is-not-absolute","errorCode":null,"errorMessage":"ExternalDoltConfig: TLSCert %q is not absolute","messagePattern":"ExternalDoltConfig: TLSCert %q is not absolute","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configfile/external_dolt_config.go","lineNumber":71,"sourceCode":"\t}\n\n\tif hasHost && (c.Port < 1 || c.Port > 65535) {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: Port %d out of range [1, 65535]\", c.Port)\n\t}\n\n\tif hasSocket && !filepath.IsAbs(c.Socket) {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: Socket %q is not absolute\", c.Socket)\n\t}\n\n\tswitch {\n\tcase c.TLSCert != \"\" && c.TLSKey == \"\":\n\t\treturn errors.New(\"ExternalDoltConfig: TLSCert set without TLSKey\")\n\tcase c.TLSCert == \"\" && c.TLSKey != \"\":\n\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\")","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/configfile/external_dolt_config.go#L53-L89","documentation":"ExternalDoltConfig.Validate requires TLSCert to be an absolute path when set. Client certificate files are read from disk during TLSClientConfig, and a relative path would depend on the process working directory, which is not guaranteed. This check runs at configuration validation time, before any connection is attempted.","triggerScenarios":"Calling Validate (via NewExternalDoltServer, NewExternalDoltServerUOWProvider, or buildProxiedServerClientInfo) with TLSCert set to a relative path like \"certs/client.pem\" or an unexpanded \"~/certs/client.pem\" (tilde is not absolute in Go).","commonSituations":"Config written with \"~/...\" paths assuming shell-style expansion; config files shared across machines with different cert locations; running the tool from a directory different from where the config was authored.","solutions":["Replace the TLSCert value with an absolute path, e.g. \"/etc/beads/tls/client.pem\".","Expand \"~/\" and environment variables before writing them into the config.","If mutual TLS is not needed, remove TLSCert (and TLSKey) entirely."],"exampleFix":"// before\ntlsCert: \"~/certs/client.pem\"\n// after\ntlsCert: \"/home/alice/certs/client.pem\"","handlingStrategy":"validation","validationCode":"func validTLSCert(cfg configfile.ExternalDoltConfig) error {\n    if cfg.TLSCert != \"\" && !filepath.IsAbs(cfg.TLSCert) {\n        return fmt.Errorf(\"TLSCert must be absolute: %q\", cfg.TLSCert)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never write \"~/\" paths into configs — Go does not expand tilde","Generate config values with a script that resolves absolute paths at write time","Keep certs in a fixed absolute location like /etc/beads/tls/"],"tags":["config","validation","tls","path"],"backgroundTag":"invalid-config-value","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}