dgraph-io/badger · error

ErrInvalidEncryptionKey

ErrInvalidEncryptionKey

Error message

Encryption key's length shouldeither 16, 24, or 32 bytes

What it means

ErrInvalidEncryptionKey is returned by OpenKeyRegistry when the supplied EncryptionKey option has a length other than 16, 24, or 32 bytes (AES-128/192/256). Badger validates key size before building the registry.

Source

Thrown at errors.go:107

	ErrTruncateNeeded = stderrors.New(
		"Log truncate required to run DB. This might result in data loss")

	// ErrBlockedWrites is returned if the user called DropAll. During the process of dropping all
	// data from Badger, we stop accepting new writes, by returning this error.
	ErrBlockedWrites = stderrors.New("Writes are blocked, possibly due to DropAll or Close")

	// ErrNilCallback is returned when subscriber's callback is nil.
	ErrNilCallback = stderrors.New("Callback cannot be nil")

	// ErrEncryptionKeyMismatch is returned when the storage key is not
	// matched with the key previously given.
	ErrEncryptionKeyMismatch = stderrors.New("Encryption key mismatch")

	// ErrInvalidDataKeyID is returned if the datakey id is invalid.
	ErrInvalidDataKeyID = stderrors.New("Invalid datakey id")

	// ErrInvalidEncryptionKey is returned if length of encryption keys is invalid.
	ErrInvalidEncryptionKey = stderrors.New("Encryption key's length should be" +
		"either 16, 24, or 32 bytes")
	// ErrGCInMemoryMode is returned when db.RunValueLogGC is called in in-memory mode.
	ErrGCInMemoryMode = stderrors.New("Cannot run value log GC when DB is opened in InMemory mode")

	// ErrGCInReadOnlyMode is returned when db.RunValueLogGC is called in read-only mode.
	ErrGCInReadOnlyMode = stderrors.New("Cannot run value log GC when DB is opened in ReadOnly mode")

	// ErrDBClosed is returned when a get operation is performed after closing the DB.
	ErrDBClosed = stderrors.New("DB Closed")
)

View on GitHub (pinned to 2a001d466f)

Solutions

  1. Generate a key of exactly 16, 24, or 32 bytes (e.g. crypto/rand.Read(make([]byte, 32)))
  2. Decode base64/hex-encoded keys before assigning to opt.EncryptionKey and check the decoded length
  3. Derive an AES key from a password with a KDF (e.g. scrypt/argon2) sized to 32 bytes
  4. Add a startup assertion: len(key) must be 16, 24, or 32 before opening the DB

Example fix

// before
opts.EncryptionKey = []byte(os.Getenv("DB_KEY")) // arbitrary length
// after
raw, _ := base64.StdEncoding.DecodeString(os.Getenv("DB_KEY"))
if len(raw) != 32 {
    return errors.New("DB_KEY must decode to 32 bytes")
}
opts.EncryptionKey = raw
Defensive patterns

Strategy: validation

Validate before calling

switch len(key) {
case 16, 24, 32:
    // ok
default:
    return fmt.Errorf("encryption key must be 16, 24, or 32 bytes, got %d", len(key))
}

Type guard

func isValidAESKey(key []byte) bool {
    return len(key) == 16 || len(key) == 24 || len(key) == 32
}

Prevention

When it happens

Trigger: Calling OpenKeyRegistry (or opening a DB with encryption enabled) with opt.EncryptionKey set to an empty slice, a raw passphrase string, a base64 string not yet decoded, or a hex-decoded key of the wrong length.

Common situations: Passing a human password instead of a derived AES key; forgetting base64 decoding of a key from env/config; truncating a 32-byte key to fewer bytes; generating keys with an entropy function returning arbitrary-length slices.

Related errors


AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05). Data as JSON: /api/errors/3334dfd539f547b3. Report an issue: GitHub.