OrchardCMS/OrchardCore · error · FileStoreException

Error getting file stream for

Error message

Error getting file stream for '{path}': {ex.Message}

What it means

Any AmazonS3Exception from GetFileStreamAsync other than 404 is wrapped in FileStoreException 'Error getting file stream for ...' with the S3 message and inner exception. It reports general failures (auth, permissions, network) while opening the object stream.

Solutions

  1. Read the inner exception message to identify the S3 error code (AccessDenied, SlowDown, etc.).
  2. Verify credentials and IAM s3:GetObject permission for the bucket/prefix.
  3. Match the configured region/service URL to the bucket region.
  4. Add retry with backoff for throttling or transient 5xx errors.

Example fix

// before
var stream = await fileStore.GetFileStreamAsync(path);

// after
try
{
    var stream = await fileStore.GetFileStreamAsync(path);
}
catch (FileStoreException ex) when (ex.Message.Contains("AccessDenied"))
{
    _logger.LogError(ex, "Access denied reading '{Path}' from S3", path);
    throw;
}
Defensive patterns

Strategy: retry

Try / catch

try
{
    return await fileStore.GetFileStreamAsync(path);
}
catch (FileStoreException ex) when (ex.Message.Contains("SlowDown") || ex.Message.Contains("ServiceUnavailable"))
{
    await Task.Delay(TimeSpan.FromSeconds(1));
    return await fileStore.GetFileStreamAsync(path);
}

Prevention

When it happens

Trigger: GetFileStreamAsync when TransferUtility.OpenStreamAsync throws non-404 errors: AccessDenied, invalid credentials, wrong region/endpoint, network timeouts, throttling.

Common situations: IAM policy missing s3:GetObject, expired or rotated credentials, VPC endpoint/proxy blocking S3, bucket region mismatch, transient AWS throttling under load.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/76a9887cb9b2d587. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore/OrchardCore.FileStorage.AmazonS3/AwsFileStorage.cs:264

        {
            throw new FileStoreException($"Error while copying file '{srcPath}': {ex.Message}", ex);
        }
    }

    public Task<Stream> GetFileStreamAsync(string path)
    {
        try
        {
            var transferUtility = new TransferUtility(_amazonS3Client);
            return transferUtility.OpenStreamAsync(_options.BucketName, this.Combine(_basePrefix, path));
        }
        catch (AmazonS3Exception ex) when (ex.StatusCode == HttpStatusCode.NotFound)
        {
            throw new FileStoreException($"Cannot get file stream because the file '{path}' does not exist.");
        }
        catch (AmazonS3Exception ex)
        {
            throw new FileStoreException($"Error getting file stream for '{path}': {ex.Message}", ex);
        }
    }

    public Task<Stream> GetFileStreamAsync(IFileStoreEntry fileStoreEntry)
    {
        return GetFileStreamAsync(fileStoreEntry.Path);
    }

    public async Task<string> CreateFileFromStreamAsync(string path, Stream inputStream, bool overwrite = false)
    {
        try
        {
            if (!overwrite)
            {
                var listObjects = await _amazonS3Client.ListObjectsV2Async(new ListObjectsV2Request
                {
                    BucketName = _options.BucketName,
                    Prefix = this.Combine(_basePrefix, path),

View on GitHub (pinned to 4306c0717f)