{"record":{"id":"2534b64509d5fe2f","repo":"juicedata/juicefs","slug":"build-tls-config-from-s-s","errorCode":null,"errorMessage":"build tls config from %s: %s","messagePattern":"build tls config from (.+?): (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/tkv_etcd.go","lineNumber":338,"sourceCode":"\t\treturn nil, fmt.Errorf(\"parse %s: %s\", addr, err)\n\t}\n\tpasswd, _ := u.User.Password()\n\thosts := strings.Split(u.Host, \",\")\n\tfor i, h := range hosts {\n\t\th, _, err := net.SplitHostPort(h)\n\t\tif err != nil {\n\t\t\thosts[i] = net.JoinHostPort(h, \"2379\")\n\t\t}\n\t}\n\tconf := etcd.Config{\n\t\tEndpoints:        hosts,\n\t\tUsername:         u.User.Username(),\n\t\tPassword:         passwd,\n\t\tAutoSyncInterval: time.Minute,\n\t}\n\tconf.TLS, err = buildTlsConfig(u)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"build tls config from %s: %s\", u.RawQuery, err)\n\t}\n\tc, err := etcd.New(conf)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tmaxCompactSlices = 100\n\tvar prefix string = u.Path + \"\\xFD\"\n\treturn withPrefix(&etcdClient{c, etcd.NewKV(c)}, []byte(prefix)), nil\n}\n\nfunc init() {\n\tRegister(\"etcd\", newKVMeta)\n\tdrivers[\"etcd\"] = newEtcdClient\n}\n","sourceCodeStart":320,"sourceCodeEnd":353,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/tkv_etcd.go#L320-L353","documentation":"When building the etcd client, JuiceFS constructs a TLS config from the connection URL's query parameters (via `buildTlsConfig`). Failure reading certificate/key/CA files or invalid PEM content produces 'build tls config from %s: %s' with the raw query string included.","triggerScenarios":"Metadata URL contains TLS query parameters (e.g. `?cert=...&key=...&cacert=...` or `sslMode`-style flags) that cannot be turned into a tls.Config: files missing, unreadable (permissions), or malformed PEM, or unsupported parameter combinations.","commonSituations":"Wrong paths to cert/key/CA files; certs not mounted/copied into containers; file permission issues; certificate files that are actually empty or corrupted; mixing https endpoint with missing CA config.","solutions":["Read the wrapped error to see which file failed (not found / permission denied / PEM parse) and fix that path or permission","Verify the query parameters in the metadata URL point to existing cert, key, and cacert files on the client machine","Validate PEM files: `openssl x509 -in cert.pem -noout` / `openssl rsa -in key.pem -check`","In containers, mount the secret/cert files and confirm they exist before mount; drop TLS params if connecting over plain http"],"exampleFix":"// before\netcd://host:2379?cert=/etc/certs/client.crt&key=/etc/certs/client.key&cacert=/etc/certs/missing-ca.crt\n// after\ncp ca.crt /etc/certs/ca.crt && chmod 600 /etc/certs/client.key\netcd://host:2379?cert=/etc/certs/client.crt&key=/etc/certs/client.key&cacert=/etc/certs/ca.crt","handlingStrategy":"validation","validationCode":"// Verify TLS files before mounting\nfor f in (cert, key, cacert):\n    if not os.path.isfile(f): raise SystemExit(f'TLS file missing: {f}')\n    os.access(f, os.R_OK) or raise SystemExit(f'TLS file unreadable: {f}')\nsubprocess.run(['openssl','x509','-in',cert,'-noout'], check=True)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep cert/key/CA paths absolute and mounted in containers","Check file permissions on private keys","Validate PEM files with openssl after rotating certs","Only supply TLS query params when actually using https endpoints"],"tags":["etcd","tls","certificates","config","juicefs"],"backgroundTag":"invalid-config-value","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}