slackhq/nebula · error
encoded EncryptionMetadata was nil
Error message
encoded EncryptionMetadata was nil
What it means
After protobuf unmarshalling, RawNebulaEncryptedData.EncryptionMetadata must be present - it carries the Argon2 parameters and nonce needed for decryption. A decoded message with EncryptionMetadata nil means the serialized blob lacked the metadata sub-message, so decryption cannot proceed.
Source
Thrown at cert/crypto.go:206
default:
return nil, fmt.Errorf("invalid curve: %v", curve)
}
}
// UnmarshalNebulaEncryptedData will unmarshal a protobuf byte representation of a nebula cert into its
// protobuf-generated struct.
func UnmarshalNebulaEncryptedData(b []byte) (*NebulaEncryptedData, error) {
if len(b) == 0 {
return nil, fmt.Errorf("nil byte array")
}
var rned RawNebulaEncryptedData
err := proto.Unmarshal(b, &rned)
if err != nil {
return nil, err
}
if rned.EncryptionMetadata == nil {
return nil, fmt.Errorf("encoded EncryptionMetadata was nil")
}
if rned.EncryptionMetadata.Argon2Parameters == nil {
return nil, fmt.Errorf("encoded Argon2Parameters was nil")
}
params, err := unmarshalArgon2Parameters(rned.EncryptionMetadata.Argon2Parameters)
if err != nil {
return nil, err
}
ned := NebulaEncryptedData{
EncryptionMetadata: NebulaEncryptionMetadata{
EncryptionAlgorithm: rned.EncryptionMetadata.EncryptionAlgorithm,
Argon2Parameters: *params,
},
Ciphertext: rned.Ciphertext,
}View on GitHub (pinned to dd8f660c0a)
Solutions
- Ensure the encryption side populated EncryptionMetadata (via EncryptionMetadata in NebulaEncryptedData) before marshalling; re-encrypt the data with the standard EncryptAndMarshal* helpers
- Verify the blob is a NebulaEncryptedData message and not truncated or a different protobuf type
- Regenerate the encrypted artifact with the current library version
Example fix
// before
ned := &cert.NebulaEncryptedData{Ciphertext: ct}
b, _ := proto.Marshal(ned) // EncryptionMetadata missing
// after
ned := &cert.NebulaEncryptedData{EncryptionMetadata: meta, Ciphertext: ct}
b, _ := proto.Marshal(ned) Defensive patterns
Strategy: type-guard
Validate before calling
var rned cert.RawNebulaEncryptedData
if err := proto.Unmarshal(b, &rned); err != nil { return err }
if rned.EncryptionMetadata == nil { return fmt.Errorf("EncryptionMetadata missing") } Type guard
func hasEncryptionMetadata(b []byte) bool {
var r cert.RawNebulaEncryptedData
if proto.Unmarshal(b, &r) != nil { return false }
return r.EncryptionMetadata != nil
} Try / catch
ned, err := cert.UnmarshalNebulaEncryptedData(b)
if err != nil {
if strings.Contains(err.Error(), "EncryptionMetadata was nil") { /* malformed blob - re-encrypt */ }
return err
} Prevention
- Always use EncryptAndMarshal* helpers to produce blobs; never hand-assemble the protobuf
- Confirm the blob is a NebulaEncryptedData message, not another type
- Re-encrypt data produced by incomplete or older external tooling
When it happens
Trigger: Calling UnmarshalNebulaEncryptedData with protobuf bytes that parse but contain no EncryptionMetadata field - e.g. a hand-built or partially serialized RawNebulaEncryptedData, or bytes of a different message type that happen to parse.
Common situations: Constructing NebulaEncryptedData manually in tests and forgetting to set EncryptionMetadata; deserializing a truncated or wrong-version blob; passing an unrelated protobuf message by mistake.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- encoded Argon2Parameters was nil
- encoded Details was nil
- nil byte array
- Argon2Parameters Version must be at least %d and no more tha
- use of Curve25519 is not allowed in FIPS 140-only mode
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/d537a12f1768c457.
Report an issue: GitHub.