OrchardCMS/OrchardCore · error · FileStoreException

Cannot create file ' ', S3 service threw an exception

Error message

Cannot create file '{path}', S3 service threw an exception: {ex.Message}

What it means

AwsFileStore.CreateFileFromStreamAsync wraps any AmazonS3Exception raised while checking for an existing key or uploading the object (PutObjectAsync) into a FileStoreException with this message. It means the S3 service itself rejected or failed the write, as opposed to the file merely already existing (that raises ExistsFileStoreException) or an unsuccessful response. The underlying S3 error message is appended to help diagnose the real cause.

Solutions

  1. Verify BucketName, region and credentials in the AmazonS3Options — read the inner ex.Message for the specific S3 error (e.g. NoSuchBucket, AccessDenied, InvalidAccessKeyId).
  2. Check the IAM policy grants s3:PutObject (and s3:ListBucket for the overwrite pre-check) on the bucket and prefix.
  3. Confirm the bucket exists in the configured region and the app can reach the S3 endpoint (network/proxy/firewall).
  4. Validate the target path is a valid S3 key: no leading/conforming invalid characters and length ≤ 1024 bytes.

Example fix

// before
await fileStore.CreateFileFromStreamAsync("logs/app?.txt", stream);
// after
var safePath = "logs/app-2026.txt"; // valid S3 key, no invalid characters
await fileStore.CreateFileFromStreamAsync(safePath, stream);
Defensive patterns

Strategy: try-catch

Validate before calling

if (string.IsNullOrWhiteSpace(path) || path.Length > 1024)
{
    throw new ArgumentException("Invalid S3 key", nameof(path));
}
if (!overwrite && await fileStore.GetFileInfoAsync(path) != null)
{
    return; // already exists
}

Try / catch

try
{
    await fileStore.CreateFileFromStreamAsync(path, stream, overwrite);
}
catch (FileStoreException ex)
{
    // ex.InnerException is AmazonS3Exception: inspect its ErrorCode
    logger.LogError(ex.InnerException, "S3 write failed for {Path}: {Code}",
        path, (ex.InnerException as AmazonS3Exception)?.ErrorCode);
}

Prevention

When it happens

Trigger: Calling CreateFileFromStreamAsync when PutObjectAsync throws AmazonS3Exception — e.g. bucket does not exist, wrong credentials/region, insufficient s3:PutObject permission, key length over 1024 chars, invalid key characters, request timeout, or the pre-check ListObjectsV2Async fails.

Common situations: Misconfigured BucketName or region in the S3 options; IAM policy missing PutObject on the bucket/prefix; expired or wrong access/secret keys; VPC/firewall blocking the S3 endpoint; uploading to a path with invalid characters; bucket deleted or renamed after config was written.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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

Appendix: source

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

                    throw new ExistsFileStoreException($"Cannot create file '{path}' because it already exists.");
                }
            }

            var response = await _amazonS3Client.PutObjectAsync(new PutObjectRequest
            {
                BucketName = _options.BucketName,
                Key = this.Combine(_basePrefix, path),
                InputStream = inputStream,
            });

            if (!response.IsSuccessful())
            {
                throw new FileStoreException($"Cannot create file '{path}'");
            }
        }
        catch (AmazonS3Exception ex)
        {
            throw new FileStoreException($"Cannot create file '{path}', S3 service threw an exception: {ex.Message}");
        }

        return path;
    }

    private static string NormalizePrefix(string prefix)
    {
        prefix = prefix.Trim('/') + '/';
        if (prefix.Length == 1)
        {
            return string.Empty;
        }

        return prefix;
    }
}

View on GitHub (pinned to 4306c0717f)