OrchardCMS/OrchardCore · error · FileStoreException
Error retrieving file info for
Error message
Error retrieving file info for '${path}': ${ex.Message} What it means
AwsFileStorage.GetFileInfoAsync wraps unexpected AmazonS3Exception failures in FileStoreException. 404 responses are treated as 'file absent' (returns null), but any other S3 error — permissions, throttling, network, bad bucket — surfaces as this message with the path and the S3 error text as inner exception.
Solutions
- Read the inner AmazonS3Exception (ErrorCode/StatusCode) to find the root cause: fix IAM policy, region, or bucket name
- Validate Media > Amazon S3 settings (bucket, region, credentials) and run a connectivity test
- Add retry with backoff for throttling (503/SlowDown) errors
- Catch FileStoreException at call sites that must tolerate storage outages and degrade gracefully
Example fix
// before
var file = await fileStore.GetFileInfoAsync(path); // throws FileStoreException on S3 failure
// after
try { var file = await fileStore.GetFileInfoAsync(path); }
catch (FileStoreException ex) { _logger.LogError(ex, "S3 error for {Path}", path); } Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight before calls:
using var resp = await _s3.GetBucketLocationAsync(new GetBucketLocationRequest { BucketName = bucket });
if (resp.HttpStatusCode != HttpStatusCode.OK) throw new InvalidOperationException("Bucket unreachable"); Type guard
bool IsFileAbsent(FileStoreException ex) => ex.InnerException is AmazonS3Exception s3 && s3.StatusCode == HttpStatusCode.NotFound;
Try / catch
try { info = await fileStore.GetFileInfoAsync(path); } catch (FileStoreException ex) when (ex.InnerException is AmazonS3Exception s3 && s3.StatusCode != HttpStatusCode.NotFound) { _logger.LogError(ex, "S3 error for {Path}: {Code}", path, s3.ErrorCode); } Prevention
- Validate bucket name, region and credentials at startup
- Grant least-privilege IAM (GetObject/ListBucket) and test with the AWS CLI
- Enable retry policy for throttling (503 SlowDown)
- Check App_Data logs for the inner AmazonS3Exception ErrorCode
When it happens
Trigger: Calling GetFileInfoAsync(path) when the S3 HEAD/Get-objects call fails with a non-404 AmazonS3Exception: invalid bucket name, missing IAM permissions, wrong region/credentials, or transient S3 throttling.
Common situations: Misconfigured AWS credentials/region in Media storage settings; IAM policy lacking s3:ListBucket/GetObject on the bucket prefix; bucket deleted or renamed while the module still points to it; S3 503 slowdown responses under load.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Error creating directory
- Error deleting file
- Cannot create file ' ', S3 service threw an exception
- Cannot delete root directory.
- Error accessing file
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/d1f0459773be9720.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.FileStorage.AmazonS3/AwsFileStorage.cs:52
public async Task<IFileStoreEntry> GetFileInfoAsync(string path)
{
try
{
var objectMetadata = await _amazonS3Client.GetObjectMetadataAsync(new GetObjectMetadataRequest
{
BucketName = _options.BucketName,
Key = this.Combine(_basePrefix, path),
});
return new AwsFile(path, objectMetadata.ContentLength, objectMetadata.LastModified);
}
catch (AmazonS3Exception ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
return null;
}
catch (AmazonS3Exception ex)
{
throw new FileStoreException($"Error retrieving file info for '{path}': {ex.Message}", ex);
}
}
public async Task<IFileStoreEntry> GetDirectoryInfoAsync(string path)
{
if (string.IsNullOrEmpty(path))
{
return new AwsDirectory(path, _clock.UtcNow);
}
var awsDirectory = await _amazonS3Client.ListObjectsV2Async(new ListObjectsV2Request
{
BucketName = _options.BucketName,
Prefix = NormalizePrefix(this.Combine(_basePrefix, path)),
MaxKeys = 1,
FetchOwner = false,
});
View on GitHub (pinned to 4306c0717f)