{"record":{"id":"ba64484bf9607545","repo":"abpframework/abp","slug":"unknown-blob-encryption-key-source-keysource-ba6448","errorCode":null,"errorMessage":"Unknown BLOB encryption key source: {keySource}!","messagePattern":"Unknown BLOB encryption key source: (.+?)!","errorType":"exception","errorClass":"AbpException","httpStatus":null,"severity":"error","filePath":"framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/DefaultBlobEncryptionKeyProvider.cs","lineNumber":75,"sourceCode":"        cancellationToken.ThrowIfCancellationRequested();\n\n        string? passPhrase;\n        switch (keySource)\n        {\n            case BlobEncryptionKeySource.Container:\n                passPhrase = GetContainerPassPhraseOrNull(context.Configuration);\n                break;\n            case BlobEncryptionKeySource.Tenant:\n                throw new AbpException(\n                    \"The BLOB was encrypted with a tenant-specific passphrase, but the default \" +\n                    $\"key provider does not supply tenant keys. Replace the {nameof(IBlobEncryptionKeyProvider)} \" +\n                    \"service with the implementation that was used to encrypt the BLOB.\"\n                );\n            case BlobEncryptionKeySource.Global:\n                passPhrase = Options.DefaultPassPhrase;\n                break;\n            default:\n                throw new AbpException($\"Unknown BLOB encryption key source: {keySource}!\");\n        }\n\n        if (string.IsNullOrWhiteSpace(passPhrase))\n        {\n            throw new AbpException(\n                $\"The BLOB was encrypted with the '{keySource}' passphrase, \" +\n                \"but that passphrase is not available anymore, so the BLOB can not be decrypted.\"\n            );\n        }\n\n        return Task.FromResult(passPhrase!);\n    }\n\n    /// <summary>\n    /// Returns the container-specific passphrase, so derived providers can keep it\n    /// as the highest-priority source.\n    /// </summary>\n    protected virtual string? GetContainerPassPhraseOrNull(BlobContainerConfiguration configuration)","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/abpframework/abp/blob/7ed43b1931b9df46a50c0c59148a18645641d0df/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/DefaultBlobEncryptionKeyProvider.cs#L57-L93","documentation":"The default branch of the switch over BlobEncryptionKeySource in ResolveForDecryptionAsync. It fires when the keySource value recorded in the BLOB header does not match Container, Tenant, or Global. This is a defensive guard: the enum is a byte stored in the BLOB, so an out-of-range value indicates either a future enum value the default provider does not yet know, or BLOB header corruption.","triggerScenarios":"ResolveForDecryptionAsync receives a BlobEncryptionKeySource whose underlying byte is not 1, 2, or 3. Occurs when a newer version of the library wrote a new enum value into the BLOB header and an older runtime reads it, or when the header bytes are physically corrupted.","commonSituations":"Downgrading the ABP BlobStoring package to a version that predates a newly added BlobEncryptionKeySource member; reading a BLOB whose encryption header was tampered with or truncated; mixing incompatible library versions across write and read hosts.","solutions":["Align the BlobStoring package version on the reading host with (or newer than) the host that wrote the BLOB.","Inspect the BLOB header bytes to confirm the recorded key source value; if corrupted, restore the BLOB from backup.","If you extended BlobEncryptionKeySource with a custom value, subclass DefaultBlobEncryptionKeyProvider and override ResolveForDecryptionAsync to handle it.","Re-encrypt the BLOB with a known key source after fixing the version skew."],"exampleFix":"// before: default switch throws on a custom/unknown key source\n// after: override to handle the extra source\npublic class ExtendedBlobEncryptionKeyProvider : DefaultBlobEncryptionKeyProvider\n{\n    public override Task<string> ResolveForDecryptionAsync(BlobEncryptionKeySource keySource, BlobEncryptionKeyContext context, CancellationToken ct = default)\n    {\n        if (Enum.IsDefined(typeof(BlobEncryptionKeySource), keySource))\n            return base.ResolveForDecryptionAsync(keySource, context, ct);\n\n        throw new AbpException($\"Unrecognized key source byte '{(byte)keySource}' in BLOB header; possible corruption or version skew.\");\n    }\n}","handlingStrategy":"validation","validationCode":"// Reject unknown key source bytes before calling the provider.\nif (!Enum.IsDefined(typeof(BlobEncryptionKeySource), keySource))\n{\n    throw new InvalidDataException($\"BLOB header records an unrecognized key source byte: {(byte)keySource}.\");\n}","typeGuard":"public static bool IsKnownKeySource(BlobEncryptionKeySource source) =>\n    Enum.IsDefined(typeof(BlobEncryptionKeySource), source);","tryCatchPattern":"try\n{\n    phrase = await keyProvider.ResolveForDecryptionAsync(keySource, context, ct);\n}\ncatch (AbpException ex) when (ex.Message.Contains(\"Unknown BLOB encryption key source\", StringComparison.Ordinal))\n{\n    logger.LogError(\"Possible version skew or BLOB header corruption; key source byte = {Byte}.\", (byte)keySource);\n    throw;\n}","preventionTips":["Keep the BlobStoring package version consistent across all hosts that read/write the same BLOBs.","Validate BLOB header bytes against the known enum range before decryption.","When extending BlobEncryptionKeySource, override the default provider to handle new members.","Back up BLOBs before migrating library versions so headers can be re-encrypted."],"tags":["blob-storing","encryption","versioning","data-corruption"],"backgroundTag":null,"analyzedSha":"7ed43b1931b9df46a50c0c59148a18645641d0df","analyzedAt":"2026-08-13T16:26:11.351Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}