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

  1. Ensure the private key bytes are actually loaded before calling the API — read the key file and check len(data) > 0
  2. Regenerate the signing key (e.g. openssl genpkey ...) and re-upload it
  3. In tests, supply a valid non-empty PEM-encoded RSA key in the Key payload
  4. 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

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


AI-assisted analysis of zitadel/zitadel@13948f2bcd (2026-09-06). Data as JSON: /api/errors/d5a96afbe778e17e. Report an issue: GitHub.