This is what happens when AWS S3 meets a read-only IAM role and your service depends on gRPC calls. The error is quiet but deadly: PermissionDenied or AccessDenied slip through gRPC like a whisper. You check credentials. You check bucket policies. You check endpoints. Still broken.
The root cause often hides in IAM role trust policies or object-level permissions. A read-only role can list and get objects, but gRPC frameworks and storage SDKs may try other calls—like HeadObject or GetBucketLocation—that require extra permissions. If the role lacks those, the gRPC client fails even when the bucket policy looks fine.
Another trap: signed URLs. If your gRPC service generates pre-signed URLs for S3 read, ensure the role can perform s3:GetObject on the right resource ARN—arn:aws:s3:::bucket-name/* with the trailing /* matters. Without it, you’ll see gRPC I/O errors that feel like network issues but are really hidden authorization failures.
When debugging, capture the exact AWS SDK error inside your gRPC service, not just the gRPC wrapper. Turn on SDK-level logging. Match the failing calls to IAM permissions. This isolates missing actions quickly. For read-only S3 roles, confirm at least these are in place: