abpframework/abp · error · AbpException
The BLOB was encrypted with a tenant-specific passphrase, bu
Error message
The BLOB was encrypted with a tenant-specific passphrase, but the default key provider does not supply tenant keys. Replace the IBlobEncryptionKeyProvider service with the implementation that was used to encrypt the BLOB.
What it means
Thrown by the default IBlobEncryptionKeyProvider when decrypting a BLOB whose header records BlobEncryptionKeySource.Tenant. The default provider only resolves container and global passphrases; it deliberately never invents tenant keys. A BLOB that was encrypted with a tenant-specific passphrase can only be decrypted by the same custom provider that produced it.
Source
Thrown at framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/DefaultBlobEncryptionKeyProvider.cs:66
}
/// <inheritdoc />
public virtual Task<string> ResolveForDecryptionAsync(
BlobEncryptionKeySource keySource,
[NotNull] BlobEncryptionKeyContext context,
CancellationToken cancellationToken = default)
{
Check.NotNull(context, nameof(context));
cancellationToken.ThrowIfCancellationRequested();
string? passPhrase;
switch (keySource)
{
case BlobEncryptionKeySource.Container:
passPhrase = GetContainerPassPhraseOrNull(context.Configuration);
break;
case BlobEncryptionKeySource.Tenant:
throw new AbpException(
"The BLOB was encrypted with a tenant-specific passphrase, but the default " +
$"key provider does not supply tenant keys. Replace the {nameof(IBlobEncryptionKeyProvider)} " +
"service with the implementation that was used to encrypt the BLOB."
);
case BlobEncryptionKeySource.Global:
passPhrase = Options.DefaultPassPhrase;
break;
default:
throw new AbpException($"Unknown BLOB encryption key source: {keySource}!");
}
if (string.IsNullOrWhiteSpace(passPhrase))
{
throw new AbpException(
$"The BLOB was encrypted with the '{keySource}' passphrase, " +
"but that passphrase is not available anymore, so the BLOB can not be decrypted."
);
}View on GitHub (pinned to 7ed43b1931)
Solutions
- Register the custom IBlobEncryptionKeyProvider implementation that was used to encrypt the BLOB (Replace it in the module's ConfigureServices: context.Services.Replace(ServiceDescriptor.Transient<IBlobEncryptionKeyProvider, YourTenantKeyProvider>())).
- Verify the custom provider's ResolveForDecryptionAsync handles BlobEncryptionKeySource.Tenant and returns the same passphrase originally used.
- If tenant-specific encryption is not actually required, re-encrypt the affected BLOBs with a container or global passphrase and update the header source.
- Confirm the correct module that registers the custom provider is added to your host's DependsOn list.
Example fix
// before: only default provider registered, tenant BLOBs fail to decrypt
// after: in your host module.ConfigureServices
context.Services.Replace(ServiceDescriptor.Transient<IBlobEncryptionKeyProvider, TenantBlobEncryptionKeyProvider>());
public class TenantBlobEncryptionKeyProvider : IBlobEncryptionKeyProvider
{
public Task<BlobEncryptionKey> ResolveForEncryptionAsync(BlobEncryptionKeyContext context, CancellationToken ct = default)
{
var phrase = ResolveTenantPassPhrase(context.TenantId);
return Task.FromResult(new BlobEncryptionKey(BlobEncryptionKeySource.Tenant, phrase));
}
public Task<string> ResolveForDecryptionAsync(BlobEncryptionKeySource keySource, BlobEncryptionKeyContext context, CancellationToken ct = default)
{
if (keySource == BlobEncryptionKeySource.Tenant)
return Task.FromResult(ResolveTenantPassPhrase(context.TenantId));
// fall back to container/global logic or delegate to DefaultBlobEncryptionKeyProvider
throw new AbpException($"Unsupported key source for decryption: {keySource}");
}
} Defensive patterns
Strategy: validation
Validate before calling
// Before decrypting tenant-encrypted BLOBs, ensure a tenant-capable provider is registered.
var provider = serviceProvider.GetService<IBlobEncryptionKeyProvider>();
if (provider is DefaultBlobEncryptionKeyProvider && blobHeaderKeySource == BlobEncryptionKeySource.Tenant)
{
throw new InvalidOperationException(
"Cannot decrypt a tenant-encrypted BLOB with the default key provider; register a tenant-aware IBlobEncryptionKeyProvider.");
} Type guard
public static bool IsTenantKeySourceSupported(IBlobEncryptionKeyProvider provider)
{
return provider is not DefaultBlobEncryptionKeyProvider;
} Try / catch
try
{
var phrase = await keyProvider.ResolveForDecryptionAsync(keySource, context, ct);
}
catch (AbpException ex) when (ex.Message.Contains("tenant-specific passphrase", StringComparison.Ordinal))
{
// Surface a clear action: register the custom tenant key provider that encrypted the BLOB.
logger.LogError(ex, "Tenant key provider missing; cannot decrypt BLOB {BlobName}.", context.BlobName);
throw;
} Prevention
- Always deploy the custom IBlobEncryptionKeyProvider alongside tenant-encrypted BLOBs across every environment that reads them.
- Record which key source each BLOB uses and assert the correct provider is registered at startup.
- Keep tenant key resolution logic under test with representative tenant IDs.
- Document the provider registration requirement in the module that enables tenant encryption.
When it happens
Trigger: ResolveForDecryptionAsync is called with keySource == BlobEncryptionKeySource.Tenant while the DI container resolves DefaultBlobEncryptionKeyProvider (no custom IBlobEncryptionKeyProvider registered). This happens when a BLOB was written by a tenant-aware custom provider and is later read in an environment where only the default provider is wired up.
Common situations: Migrating encrypted BLOBs between environments; deploying a host that reads tenant-encrypted BLOBs without registering the custom key provider; removing or renaming the custom IBlobEncryptionKeyProvider registration; multi-tenant setups where tenant key resolution was intended but never implemented.
Related errors
- The BLOB was encrypted with the '{keySource}' passphrase, bu
- Unknown BLOB encryption key source: {keySource}!
- No BLOB Storage provider was registered! At least one provid
- No BLOB Storage provider was used! At least one provider mus
- Could not find the BLOB Storage provider with the type ({con
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/9f334c0d5a9f646e.
Report an issue: GitHub.