zitadel/zitadel · error
cannot decode, empty data
Error message
cannot decode, empty data
What it means
ErrEmpty in internal/crypto/rsa.go is returned by the key-decoding helpers (e.g. BytesToPublicKey, BytesToPrivateKeyPKCS8) when the input byte slice is empty (len == 0). ZITADEL cannot decode an empty buffer into a key, so it fails fast with this sentinel error instead of a PEM parse error. It surfaces as an invalid-argument error in higher layers.
Source
Thrown at internal/crypto/rsa.go:209
var zero T
if len(priv) == 0 {
return zero, ErrEmpty
}
block, _ := pem.Decode(priv)
if block == nil {
return zero, ErrEmpty
}
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return zero, err
}
if k, ok := key.(T); ok {
return k, nil
}
return zero, zerrors.ThrowInvalidArgumentf(nil, "CRYP-9n2s3", "wrong type: expected %T, got %T", zero, key)
}
var ErrEmpty = errors.New("cannot decode, empty data")
var ErrNoPublicKey = errors.New("unsupported public key type")
func BytesToPublicKey(pub []byte) (crypto.PublicKey, error) {
if len(pub) == 0 {
return nil, ErrEmpty
}
block, _ := pem.Decode(pub)
if block == nil {
return nil, ErrEmpty
}
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
switch key.(type) {
case *rsa.PublicKey,
*ecdsa.PublicKey,
ed25519.PublicKey:View on GitHub (pinned to 13948f2bcd)
Solutions
- Ensure the private key bytes are actually loaded before calling the API — read the key file and check len(data) > 0
- Regenerate the signing key (e.g. openssl genpkey ...) and re-upload it
- In tests, supply a valid non-empty PEM-encoded RSA key in the Key payload
- Validate input in your client code before the call: if len(key) == 0 { return error }
Example fix
// before
keyData, _ := os.ReadFile(cfg.KeyFile) // silently empty on error
// after
keyData, err := os.ReadFile(cfg.KeyFile)
if err != nil || len(keyData) == 0 {
return fmt.Errorf("IDP private key missing or empty: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
if len(privateKeyPEM) == 0 {
return errors.New("IDP private key is empty")
} Type guard
func hasKeyData(b []byte) bool { return len(b) > 0 && bytes.HasPrefix(bytes.TrimSpace(b), []byte("-----BEGIN")) } Try / catch
if err := idp.AddGenericOIDC(ctx, ...); errors.Is(err, crypto.ErrEmpty) {
return fmt.Errorf("IDP private key missing/empty: %w", err)
} Prevention
- Read key files with error handling; never ignore the error from os.ReadFile
- Validate key material (non-empty, PEM-prefixed) before submitting IDP config
- Keep test fixtures with real generated keys, not empty placeholders
When it happens
Trigger: Calling BytesToPublicKey/BytesToPrivateKeyPKCS8 with a zero-length []byte; command layer (instance_idp/org_idp) adding a generic/machine IDP with an empty private key blob, mapped to INST-Fk38d / ORG-Fk38d 'Errors.IDP.InvalidPrivateKey'.
Common situations: Uploading a generic OIDC/JWT IDP config where the private key file was empty or not read; generating a key into a variable that was never populated; test fixtures passing empty key data.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- unsupported public key type
- QUOTA-8YXPk
- TLS is enabled: please specify a key (path) and a cert (path
- MaxOpenConns of the database must be higher than 3 or 0 for
- user does not exist or too many entries returned
AI-assisted analysis of zitadel/zitadel@13948f2bcd (2026-09-06).
Data as JSON: /api/errors/d5a96afbe778e17e.
Report an issue: GitHub.