abpframework/abp · error · AbpException
The BLOB was encrypted with the '{keySource}' passphrase, bu
Error message
The BLOB was encrypted with the '{keySource}' passphrase, but that passphrase is not available anymore, so the BLOB can not be decrypted. What it means
Thrown after the switch in ResolveForDecryptionAsync resolves the key source but the resulting passphrase is null, empty, or whitespace. The BLOB header knows which source was used (container or global), but that source no longer yields a value, so decryption is impossible. This is distinct from error 100 (unsupported source) and error 101 (unknown source).
Source
Thrown at framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/DefaultBlobEncryptionKeyProvider.cs:80
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."
);
}
return Task.FromResult(passPhrase!);
}
/// <summary>
/// Returns the container-specific passphrase, so derived providers can keep it
/// as the highest-priority source.
/// </summary>
protected virtual string? GetContainerPassPhraseOrNull(BlobContainerConfiguration configuration)
{
return BlobEncryptionConfiguration.GetPassPhraseOrNull(configuration);
}
}
View on GitHub (pinned to 7ed43b1931)
Solutions
- Restore the passphrase that was active when the BLOB was encrypted (container passphrase via UseEncryption, or AbpBlobStoringEncryptionOptions.DefaultPassPhrase), then decrypt.
- If the original passphrase is truly lost, accept the BLOB is unrecoverable and re-create it.
- Maintain a passphrase history/keystore so older BLOBs can always be decrypted during rotations.
- After restoring access, re-encrypt the BLOB with the current passphrase and update tooling to prevent silent passphrase removal.
Example fix
// before: DefaultPassPhrase was removed from appsettings, decryption fails
// after: restore the original global passphrase in the module
Configure<AbpBlobStoringEncryptionOptions>(options =>
{
options.DefaultPassPhrase = _originalPassPhraseFromSecretStore;
}); Defensive patterns
Strategy: validation
Validate before calling
// Verify the recorded key source still resolves to a passphrase before decryption.
var probe = keySource switch
{
BlobEncryptionKeySource.Container => containerPassPhrase,
BlobEncryptionKeySource.Global => options.DefaultPassPhrase,
_ => null
};
if (string.IsNullOrWhiteSpace(probe))
{
throw new InvalidOperationException($"The passphrase for key source '{keySource}' is no longer configured; decryption will fail.");
} Type guard
public static bool HasPassphraseForSource(BlobEncryptionKeySource source, string? containerPhrase, AbpBlobStoringEncryptionOptions opts) =>
source switch
{
BlobEncryptionKeySource.Container => !string.IsNullOrWhiteSpace(containerPhrase),
BlobEncryptionKeySource.Global => !string.IsNullOrWhiteSpace(opts.DefaultPassPhrase),
_ => false
}; Try / catch
try
{
phrase = await keyProvider.ResolveForDecryptionAsync(keySource, context, ct);
}
catch (AbpException ex) when (ex.Message.Contains("not available anymore", StringComparison.Ordinal))
{
logger.LogError(ex, "Passphrase for source {Source} is missing; restore config or re-encrypt the BLOB.", keySource);
throw;
} Prevention
- Treat passphrases as immutable operational secrets; never delete one without re-encrypting affected BLOBs.
- Keep a passphrase history so rotated keys can still decrypt legacy BLOBs.
- Add a startup health check that confirms the expected passphrases are configured.
- Alert when a configured container/global passphrase becomes null or empty.
When it happens
Trigger: keySource is Container but GetContainerPassPhraseOrNull returns null (no per-container passphrase configured), or keySource is Global but AbpBlobStoringEncryptionOptions.DefaultPassPhrase is unset/blank. The BLOB was encrypted when the passphrase existed; it was later removed or renamed in configuration.
Common situations: Rotating or deleting a passphrase without re-encrypting existing BLOBs; moving config between environments where AbpBlobStoringEncryptionOptions.DefaultPassPhrase was not copied; removing the UseEncryption(...) container passphrase; changing appsettings without the encryption block.
Related errors
- The BLOB was encrypted with a tenant-specific 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/0af70318d36a87c6.
Report an issue: GitHub.