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

  1. Restore the passphrase that was active when the BLOB was encrypted (container passphrase via UseEncryption, or AbpBlobStoringEncryptionOptions.DefaultPassPhrase), then decrypt.
  2. If the original passphrase is truly lost, accept the BLOB is unrecoverable and re-create it.
  3. Maintain a passphrase history/keystore so older BLOBs can always be decrypted during rotations.
  4. 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

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


AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13). Data as JSON: /api/errors/0af70318d36a87c6. Report an issue: GitHub.