ory/hydra · error

square/go-jose: parse error, got '%s', '%s', '%s' and '%s'

Error message

square/go-jose: parse error, got '%s', '%s', '%s' and '%s'

What it means

Aggregated parse error from LoadPrivateKey: none of the four attempted formats (PKCS1, PKCS8, EC PEM, JWK) succeeded, and the message embeds each attempt's underlying error so the real cause of the malformed private key can be diagnosed.

Source

Thrown at oryx/josex/utils.go:102

		return priv, nil
	}

	priv, err1 := x509.ParsePKCS8PrivateKey(input)
	if err1 == nil {
		return priv, nil
	}

	priv, err2 := x509.ParseECPrivateKey(input)
	if err2 == nil {
		return priv, nil
	}

	jwk, err3 := LoadJSONWebKey(input, false)
	if err3 == nil {
		return jwk, nil
	}

	return nil, fmt.Errorf("square/go-jose: parse error, got '%s', '%s', '%s' and '%s'", err0, err1, err2, err3)
}

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Read err0..err3 in the message to see each parse failure reason
  2. Confirm the input is an unencrypted PEM PRIVATE KEY (PKCS1 or PKCS8), DER private key, or JWK with a private 'd' component
  3. Decrypt password-protected keys before passing them in (openssl pkey -in key.pem)
  4. If you passed a public key or certificate, load the actual private key file
  5. Check for whitespace/newline mangling when keys come from env vars

Example fix

// before
key, err := josex.LoadPrivateKey(certPEM) // 'BEGIN CERTIFICATE'
// after
key, err := josex.LoadPrivateKey(privPEM) // 'BEGIN PRIVATE KEY'
Defensive patterns

Strategy: validation

Validate before calling

func looksLikePrivateKey(data []byte) error {
    s := strings.TrimSpace(string(data))
    switch {
    case strings.Contains(s, "BEGIN ENCRYPTED PRIVATE KEY") || strings.Contains(s, "ENCRYPTED PRIVATE KEY"):
        return errors.New("key is passphrase-protected; decrypt before loading")
    case strings.Contains(s, "BEGIN CERTIFICATE") || strings.Contains(s, "BEGIN PUBLIC KEY"):
        return errors.New("got a public key/certificate; LoadPrivateKey needs a private key")
    case strings.Contains(s, "BEGIN PRIVATE KEY"), strings.Contains(s, "BEGIN RSA PRIVATE KEY"), strings.HasPrefix(s, "{\"kty\""):
        return nil
    default:
        return errors.New("input is not a PEM private key, DER private key, or JWK")
    }
}

Type guard

func isPEMPrivateKey(data []byte) bool {
    s := string(data)
    return strings.Contains(s, "BEGIN PRIVATE KEY") || strings.Contains(s, "BEGIN RSA PRIVATE KEY")
}

Try / catch

key, err := josex.LoadPrivateKey(data)
if err != nil {
    return fmt.Errorf("invalid private key material: %w", err)
}

Prevention

When it happens

Trigger: Calling josex.LoadPrivateKey with a public key instead of a private key, a certificate PEM, encrypted (password-protected) private key PEM, raw base64 of key material, or corrupt/empty data.

Common situations: Swapped pub/priv file paths in config; passphrase-protected 'ENCRYPTED PRIVATE KEY' blocks the parser cannot read; Kubernetes secrets mounted truncated; copied keys with HTML entities or escaped newlines.

Understand the failure class

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/3d845e504ed3fc84. Report an issue: GitHub.