{"record":{"id":"af6f3bff9edaa6bc","repo":"amir20/dozzle","slug":"failed-to-parse-certificate-w-af6f3b","errorCode":null,"errorMessage":"failed to parse certificate: %w","messagePattern":"failed to parse certificate: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/agent/server.go","lineNumber":563,"sourceCode":"\t\tpbStat := &pb.NotificationSubscriptionStats{\n\t\t\tSubscriptionId:        int32(s.SubscriptionID),\n\t\t\tTriggerCount:          s.TriggerCount,\n\t\t\tTriggeredContainerIds: s.TriggeredContainerIDs,\n\t\t}\n\t\tif s.LastTriggeredAt != nil {\n\t\t\tpbStat.LastTriggeredAt = timestamppb.New(*s.LastTriggeredAt)\n\t\t}\n\t\tpbStats[i] = pbStat\n\t}\n\n\treturn &pb.GetNotificationStatsResponse{Stats: pbStats}, nil\n}\n\nfunc NewServer(service ClientService, certificates tls.Certificate, dozzleVersion string, notificationHandler NotificationConfigHandler) (*grpc.Server, error) {\n\tcaCertPool := x509.NewCertPool()\n\tc, err := x509.ParseCertificate(certificates.Certificate[0])\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse certificate: %w\", err)\n\t}\n\tcaCertPool.AddCert(c)\n\n\t// Create the TLS configuration\n\ttlsConfig := &tls.Config{\n\t\tCertificates: []tls.Certificate{certificates},\n\t\tClientCAs:    caCertPool,\n\t\tClientAuth:   tls.RequireAndVerifyClientCert, // Require client certificates\n\t}\n\n\t// Create the gRPC server with the credentials\n\tcreds := credentials.NewTLS(tlsConfig)\n\n\tgrpcServer := grpc.NewServer(\n\t\tgrpc.Creds(creds),\n\t\tgrpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{\n\t\t\tMinTime:             15 * time.Second,\n\t\t\tPermitWithoutStream: true,","sourceCodeStart":545,"sourceCodeEnd":581,"githubUrl":"https://github.com/amir20/dozzle/blob/d9463cbe21874e44ab79db6fa63e746ca7d22928/internal/agent/server.go#L545-L581","documentation":"NewServer wraps the error from x509.ParseCertificate when the first leaf certificate of the supplied tls.Certificate cannot be parsed into an x509.Certificate. This certificate is used both as the server cert and added to the CA cert pool for mTLS verification of agents, so the gRPC agent server cannot be created at all. It always carries the underlying x509 parse error via %w.","triggerScenarios":"Calling internal/agent.NewServer with a tls.Certificate whose Certificate[0] is empty, malformed PEM/DER data, or otherwise not a valid X.509 certificate (e.g. cert generated by 'make generate' failed or file loaded with wrong type, like loading the key as a certificate).","commonSituations":"shared_cert.pem is empty, corrupted, or truncated; user copied a private key or CSR into the certificate file; certificates generated with an unsupported algorithm; certificate file replaced by an HTML error page or placeholder during image builds.","solutions":["Regenerate the certificates with 'make generate' and restart the agent","Inspect shared_cert.pem: it must contain a valid '-----BEGIN CERTIFICATE-----' block, not a key or CSR","Verify the code loading certificates returns tls.X509KeyPair(cert, key) correctly and errors are not swallowed","Check file permissions/read errors so the cert file is not read as empty bytes"],"exampleFix":"// before: loading cert file raw into tls.Certificate\ncert := tls.Certificate{Certificate: [][]byte{certFileBytes}}\n// after: parse a proper keypair and propagate errors\ncert, err := tls.LoadX509KeyPair(\"shared_cert.pem\", \"shared_key.pem\")\nif err != nil {\n    return fmt.Errorf(\"loading agent certs: %w\", err)\n}","handlingStrategy":"validation","validationCode":"if len(cert.Certificate) == 0 {\n    return fmt.Errorf(\"no certificate data supplied\")\n}\nif _, err := x509.ParseCertificate(cert.Certificate[0]); err != nil {\n    return fmt.Errorf(\"invalid agent certificate: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if _, err := agent.NewServer(svc, cert, version, handler); err != nil {\n    var parseErr *x509.CertificateInvalidError\n    if errors.As(err, &parseErr) { /* regenerate certs */ }\n    log.Fatalf(\"agent server init failed: %v\", err)\n}","preventionTips":["Run 'make generate' after cloning and before starting the agent","Never hand-edit shared_cert.pem; verify it starts with '-----BEGIN CERTIFICATE-----'","Fail fast at startup by validating certs before opening the gRPC listener"],"tags":["tls","x509","grpc","certificate","agent"],"backgroundTag":"invalid-argument-format","analyzedSha":"d9463cbe21874e44ab79db6fa63e746ca7d22928","analyzedAt":"2026-09-07T10:08:55.855Z","contentChangedAt":"2026-09-07T10:08:55.855Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}