{"record":{"id":"90532fa11ac39abc","repo":"bytebase/bytebase","slug":"no-valid-certificate-pem-block-found","errorCode":null,"errorMessage":"no valid CERTIFICATE PEM block found","messagePattern":"no valid CERTIFICATE PEM block found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/api/v1/instance_service.go","lineNumber":633,"sourceCode":"\t\t}\n\t}\n\tif ds.GetSslCert() != \"\" && ds.GetSslKey() == \"\" {\n\t\tif err := validateInlineCertPEM([]byte(ds.GetSslCert())); err != nil {\n\t\t\treturn errors.Wrap(err, \"invalid ssl_cert PEM\")\n\t\t}\n\t}\n\tif ds.GetSslKey() != \"\" && ds.GetSslCert() == \"\" {\n\t\tif err := validateInlineKeyPEM([]byte(ds.GetSslKey())); err != nil {\n\t\t\treturn errors.Wrap(err, \"invalid ssl_key PEM\")\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc validateInlineCAPEM(data []byte) error {\n\tpool := x509.NewCertPool()\n\tif ok := pool.AppendCertsFromPEM(data); !ok {\n\t\treturn errors.New(\"no valid CERTIFICATE PEM block found\")\n\t}\n\treturn nil\n}\n\nfunc validateInlineCertPEM(data []byte) error {\n\tvar certs [][]byte\n\tfor {\n\t\tvar block *pem.Block\n\t\tblock, data = pem.Decode(data)\n\t\tif block == nil {\n\t\t\tbreak\n\t\t}\n\t\tif block.Type == \"CERTIFICATE\" {\n\t\t\tcerts = append(certs, block.Bytes)\n\t\t}\n\t}\n\tif len(certs) == 0 {\n\t\treturn errors.New(\"no CERTIFICATE PEM block found\")","sourceCodeStart":615,"sourceCodeEnd":651,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/api/v1/instance_service.go#L615-L651","documentation":"validateInlineCAPEM appends the provided data to an x509.CertPool; AppendCertsFromPEM returns false when no valid CERTIFICATE PEM block is present, and the code turns that into this error. The ssl_ca value must contain at least one parseable PEM certificate.","triggerScenarios":"CreateInstance/UpdateInstance/AddDataSource/UpdateDataSource with inline ssl_ca that is raw DER, truncated, JSON-escaped, or otherwise contains no '-----BEGIN CERTIFICATE-----' block.","commonSituations":"Pasting a base64 DER cert instead of PEM; copying the CA from a Windows cert export in DER form; whitespace/line-ending corruption when pasting; uploading a private key file into the CA field.","solutions":["Supply the CA as PEM format including the '-----BEGIN CERTIFICATE-----' and '-----END CERTIFICATE-----' lines.","Convert DER to PEM (openssl x509 -inform der -in ca.der -out ca.pem) and re-submit.","Verify the field contains the CA certificate, not a key or the leaf certificate chain alone with corruption."],"exampleFix":"// before\nsslCa: \"MIIDdzCCAl+g...\" // raw base64 DER\n// after\nsslCa: \"-----BEGIN CERTIFICATE-----\\nMIIDdzCCAl+g...\\n-----END CERTIFICATE-----\"","handlingStrategy":"validation","validationCode":"function isPemCertificate(v) {\n  return typeof v === 'string' && v.includes('-----BEGIN CERTIFICATE-----');\n}\nif (!isPemCertificate(ds.sslCa)) throw new Error('ssl_ca must be PEM');","typeGuard":"const isPemCertificate = (v) => typeof v === 'string' && /-----BEGIN CERTIFICATE-----[\\s\\S]+-----END CERTIFICATE-----/.test(v);","tryCatchPattern":null,"preventionTips":["Always export CAs in PEM (Base64) format, not DER.","Paste certificates from plain-text tools, never rich-text editors.","Verify with `openssl x509 -in ca.pem -noout` before submitting."],"tags":["go","tls","pem","certificate","validation"],"backgroundTag":"invalid-config-value","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}