{"record":{"id":"6ae89b95ece743b9","repo":"slackhq/nebula","slug":"nil-byte-array-6ae89b","errorCode":null,"errorMessage":"nil byte array","messagePattern":"nil byte array","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cert/crypto.go","lineNumber":197,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tswitch curve {\n\tcase Curve_CURVE25519:\n\t\treturn pem.EncodeToMemory(&pem.Block{Type: EncryptedEd25519PrivateKeyBanner, Bytes: b}), nil\n\tcase Curve_P256:\n\t\treturn pem.EncodeToMemory(&pem.Block{Type: EncryptedECDSAP256PrivateKeyBanner, Bytes: b}), nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"invalid curve: %v\", curve)\n\t}\n}\n\n// UnmarshalNebulaEncryptedData will unmarshal a protobuf byte representation of a nebula cert into its\n// protobuf-generated struct.\nfunc UnmarshalNebulaEncryptedData(b []byte) (*NebulaEncryptedData, error) {\n\tif len(b) == 0 {\n\t\treturn nil, fmt.Errorf(\"nil byte array\")\n\t}\n\tvar rned RawNebulaEncryptedData\n\terr := proto.Unmarshal(b, &rned)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif rned.EncryptionMetadata == nil {\n\t\treturn nil, fmt.Errorf(\"encoded EncryptionMetadata was nil\")\n\t}\n\n\tif rned.EncryptionMetadata.Argon2Parameters == nil {\n\t\treturn nil, fmt.Errorf(\"encoded Argon2Parameters was nil\")\n\t}\n\n\tparams, err := unmarshalArgon2Parameters(rned.EncryptionMetadata.Argon2Parameters)\n\tif err != nil {\n\t\treturn nil, err","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/crypto.go#L179-L215","documentation":"UnmarshalNebulaEncryptedData requires a non-empty protobuf-encoded RawNebulaEncryptedData blob. An empty (len 0) input cannot be a valid encrypted-data message, so it is rejected up front with 'nil byte array' instead of letting proto.Unmarshal produce a vaguer error.","triggerScenarios":"Calling UnmarshalNebulaEncryptedData(nil) or UnmarshalNebulaEncryptedData([]byte{}) - typically when a PEM block decoded to nothing, a file was empty, or an upstream function returned a nil byte slice on error and its error was ignored.","commonSituations":"Reading an empty or zero-length key file; pem.Decode returning nil and dereferencing block.Bytes unguarded; a caller swallowing an earlier error and forwarding nil bytes to decryption.","solutions":["Check the input source: ensure the PEM block decoded successfully and block.Bytes is non-empty before calling","Propagate/handle earlier errors - an upstream read that failed likely returned nil, causing this downstream error","Regenerate the encrypted key file if the source file itself is empty"],"exampleFix":"// before\nblock, _ := pem.Decode(raw)\ndata, err := cert.UnmarshalNebulaEncryptedData(block.Bytes) // block may be nil\n// after\nblock, _ := pem.Decode(raw)\nif block == nil || len(block.Bytes) == 0 {\n    return fmt.Errorf(\"no encrypted nebula data found\")\n}\ndata, err := cert.UnmarshalNebulaEncryptedData(block.Bytes)","handlingStrategy":"validation","validationCode":"if len(b) == 0 { return fmt.Errorf(\"no encrypted data to unmarshal\") }","typeGuard":"func hasEncryptedData(b []byte) bool { return len(b) > 0 }","tryCatchPattern":"ned, err := cert.UnmarshalNebulaEncryptedData(b)\nif err != nil {\n    if strings.Contains(err.Error(), \"nil byte array\") { /* upstream read failed */ }\n    return err\n}","preventionTips":["Handle errors from upstream reads/decodes instead of forwarding nil bytes","Check pem.Decode success before accessing block.Bytes","Validate non-empty file contents before attempting decryption"],"tags":["crypto","protobuf","empty-input","validation"],"backgroundTag":"empty-input","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}