semaphoreui/semaphore · error
decode encryption key
Error message
decode encryption key: %w
What it means
Returned by newGCM in util/encryption.go when the configured encryption key string cannot be base64-decoded. The keyring expects AES keys as base64-encoded raw bytes (32 bytes for AES-256); a decode failure means the key in config/storage was written as literal text, mangled, or encoded with a non-standard alphabet. The %w wraps base64.CorruptInputError with the offset of the first bad character.
Solutions
- Regenerate the key as 32 random bytes and store it base64-encoded (e.g. openssl rand -base64 32)
- Check the wrapped CorruptInputError offset to find invalid characters in the current key string
- Ensure the key was not passed through a layer that altered it (whitespace trimming, URL-encoding, quote stripping)
- If secrets were encrypted under the malformed key they are unreadable — re-encrypt them after fixing the key
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at util/encryption.go:65 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/6607bf8feb1e2e8e.
Report an issue: GitHub.
Appendix: source
Thrown at util/encryption.go:65
gcm, err := newGCM(encodedKey)
if err != nil {
return nil, err
}
nonceSize := gcm.NonceSize()
if len(ciphertext) < nonceSize {
return nil, errors.New("ciphertext too short")
}
nonce, payload := ciphertext[:nonceSize], ciphertext[nonceSize:]
return gcm.Open(nil, nonce, payload, nil)
}
func newGCM(encodedKey string) (cipher.AEAD, error) {
keyBytes, err := base64.StdEncoding.DecodeString(encodedKey)
if err != nil {
return nil, fmt.Errorf("decode encryption key: %w", err)
}
block, err := aes.NewCipher(keyBytes)
if err != nil {
return nil, err
}
return cipher.NewGCM(block)
}
func GeneratePrivateKey(privateKeyFile io.Writer) (publicKey string, err error) {
// 1. Generate RSA Private Key (2048 bits)
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return
}
// 2. Encode the private key to PKCS#1 ASN.1 PEM
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
privateKeyPem := &pem.Block{View on GitHub (pinned to 1774ccb71a)