kopia/kopia · error
unable to initialize client cert credential
Error message
unable to initialize client cert credential
What it means
getAZService wraps azidentity.NewClientCertificateCredential, which builds a service-principal credential from the parsed certificate and key. This error means the credential object could not be constructed even though the certificate parsed — typically an invalid key, mismatched cert/key pair, or invalid tenant/client IDs.
Solutions
- Ensure the private key is decrypted (no passphrase) and matches the certificate (compare moduli)
- Confirm the certificate is uploaded to the service principal in Azure AD (az ad app credential reset with --cert)
- Validate TenantID and ClientID are correct GUIDs for the principal
- Re-export cert+key together with openssl and re-parse before retrying
- Use az login --service-principal --certificate as an out-of-band check
Example fix
// before openssl pkcs12 -in cert.pfx -nocerts -out key.pem // encrypted key // after openssl pkcs12 -in cert.pfx -nocerts -nodes -out key.pem // decrypted key // then verify match: // openssl x509 -noout -modulus -in cert.pem | openssl md5 // openssl rsa -noout -modulus -in key.pem | openssl md5
Defensive patterns
Strategy: validation
Validate before calling
func validateCertCredential(tenantID, clientID, certPEM string) error {
if _, err := uuid.Parse(strings.TrimSpace(tenantID)); err != nil {
return fmt.Errorf("tenant id invalid: %w", err)
}
if _, err := uuid.Parse(strings.TrimSpace(clientID)); err != nil {
return fmt.Errorf("client id invalid: %w", err)
}
// key must be unencrypted and match the cert
if strings.Contains(certPEM, "ENCRYPTED") {
return errors.New("private key must be decrypted (no passphrase)")
}
return nil
} Prevention
- Export the private key unencrypted (-nodes) when generating
- Verify cert/key match (compare modulus hashes)
- Upload the certificate to the Azure AD app registration
- Validate tenant/client GUIDs before constructing the credential
When it happens
Trigger: After ParseCertificates succeeds, NewClientCertificateCredential fails due to a malformed private key, cert/key mismatch, empty or malformed TenantID/ClientID, or invalid option values.
Common situations: Private key encrypted with a passphrase (unparseable without password); certificate and key from different principals; client certificate not uploaded/registered on the Azure AD app; GUID fields containing typos.
Related errors
- failed to read client cert
- unable to initialize client secret credential
- one of the storage key, SAS token, client secret, client…
- opening azure service
- unable to initialize Azure Federated Identity workload…
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/7d04084f662c8700.
Report an issue: GitHub.
Appendix: source
Thrown at repo/blob/azure/azure_storage.go:462
)
// client secret
case opt.TenantID != "" && opt.ClientID != "" && opt.ClientSecret != "":
cred, err := azidentity.NewClientSecretCredential(opt.TenantID, opt.ClientID, opt.ClientSecret, nil)
if err != nil {
return nil, errors.Wrap(err, "unable to initialize client secret credential")
}
service, serviceErr = azblob.NewClient(fmt.Sprintf("%s://%s/", protocol, storageHostname), cred, clientOptions)
// client certificate
case opt.TenantID != "" && opt.ClientID != "" && opt.ClientCertificate != "":
certs, key, certErr := azidentity.ParseCertificates([]byte(opt.ClientCertificate), nil)
if certErr != nil {
return nil, errors.Wrap(certErr, "failed to read client cert")
}
cred, credErr := azidentity.NewClientCertificateCredential(opt.TenantID, opt.ClientID, certs, key, nil)
if credErr != nil {
return nil, errors.Wrap(credErr, "unable to initialize client cert credential")
}
service, serviceErr = azblob.NewClient(fmt.Sprintf("%s://%s/", protocol, storageHostname), cred, clientOptions)
// Azure Federated Token
case opt.TenantID != "" && opt.ClientID != "" && opt.AzureFederatedTokenFile != "":
cred, err := azidentity.NewWorkloadIdentityCredential(&azidentity.WorkloadIdentityCredentialOptions{
ClientID: opt.ClientID,
TenantID: opt.TenantID,
TokenFilePath: opt.AzureFederatedTokenFile,
})
if err != nil {
return nil, errors.Wrap(err, "unable to initialize Azure Federated Identity workload identity credential")
}
service, serviceErr = azblob.NewClient(fmt.Sprintf("%s://%s/", protocol, storageHostname), cred, clientOptions)
default:
return nil, errors.New("one of the storage key, SAS token, client secret, client certificate, or Azure Federated Token file must be provided")
}View on GitHub (pinned to 82495e54b5)