Terraform resource configuration often has mutually exclusive arguments where you must choose one option or another, not both. This error occurs when you try to use conflicting options simultaneously in your Terraform code.
Some Terraform resource arguments cannot be used together. They are mutually exclusive by design because they represent different ways of accomplishing the same goal. When Terraform detects that you've specified two conflicting arguments at the same time, it raises this error because it cannot determine which one you intend to use.
Read the full error message carefully to see which specific arguments conflict. Terraform provides helpful output like:
Error: Conflicting configuration arguments
on main.tf line 5, in resource "aws_lambda_function" "example":
5: filename = "lambda.zip"
6: s3_bucket = "my-bucket"
'filename' and 's3_bucket'/'s3_key' cannot be used together.This tells you exactly which options in your resource cannot coexist.
For AWS Lambda, you must choose between local deployment or S3 deployment:
Option 1: Local File Deployment
resource "aws_lambda_function" "example" {
filename = "lambda_function.zip"
source_code_hash = filebase64sha256("lambda_function.zip")
function_name = "my_function"
role = aws_iam_role.lambda_role.arn
handler = "index.handler"
runtime = "nodejs18.x"
}Option 2: S3 Deployment
resource "aws_lambda_function" "example" {
s3_bucket = "my-deployment-bucket"
s3_key = "lambda_function.zip"
function_name = "my_function"
role = aws_iam_role.lambda_role.arn
handler = "index.handler"
runtime = "nodejs18.x"
}Remove all conflicting arguments and keep only one method.
If using container images (image_uri), you cannot specify handler and runtime:
# WRONG - These conflict with image_uri
resource "aws_lambda_function" "example" {
image_uri = "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-lambda:latest"
handler = "index.handler" # REMOVE THIS
runtime = "nodejs18.x" # REMOVE THIS
}
# CORRECT - Image-based Lambda
resource "aws_lambda_function" "example" {
image_uri = "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-lambda:latest"
function_name = "my_function"
role = aws_iam_role.lambda_role.arn
package_type = "Image"
}Container images define their own entry point and runtime, so these settings are redundant.
Each Terraform resource documents which arguments conflict. For example:
For aws_lambda_function:
- filename conflicts with s3_bucket and s3_key
- image_uri conflicts with filename, s3_bucket, handler, and runtime
For AWS EC2 instance:
- root_block_device and ebs_block_device cannot specify the same device
Visit the [AWS Provider documentation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) and search for your resource to see all conflicting argument pairs listed in the Argument Reference section.
If you need to support multiple deployment methods, use variables and conditional blocks:
variable "deployment_method" {
type = string
enum = ["local", "s3", "image"]
}
resource "aws_lambda_function" "example" {
function_name = "my_function"
role = aws_iam_role.lambda_role.arn
# Local deployment
filename = var.deployment_method == "local" ? "lambda.zip" : null
source_code_hash = var.deployment_method == "local" ? filebase64sha256("lambda.zip") : null
handler = var.deployment_method != "image" ? "index.handler" : null
runtime = var.deployment_method != "image" ? "nodejs18.x" : null
# S3 deployment
s3_bucket = var.deployment_method == "s3" ? "my-bucket" : null
s3_key = var.deployment_method == "s3" ? "lambda.zip" : null
# Image deployment
image_uri = var.deployment_method == "image" ? "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-lambda:latest" : null
package_type = var.deployment_method == "image" ? "Image" : "Zip"
}This allows one Terraform module to support all deployment methods while avoiding conflicts.
After removing conflicting arguments, validate your configuration:
terraform validateThis performs syntax and argument validation without connecting to AWS. If this command succeeds, you've resolved the conflict.
Understanding AWS Lambda deployment options:
1. Zip vs Container: AWS Lambda supports two package types:
- Zip: Traditional .zip deployment with handler and runtime specified
- Image: Container image with everything defined in the Dockerfile
2. Code source flexibility: Within Zip deployments, you can source code from:
- Local file system (filename)
- S3 bucket (s3_bucket + s3_key)
- Lambda code archive (if using AWS Console)
You MUST choose exactly one source method.
3. Common patterns:
- Development: Use local file with filebase64sha256() for hash
- CI/CD: Upload to S3 first, reference from Terraform
- Containers: Use ECR image with package_type = "Image"
4. Module reusability: Create separate Terraform modules for each deployment pattern to avoid complexity:
- modules/lambda-zip-local
- modules/lambda-zip-s3
- modules/lambda-image
5. Source code hash considerations: When using filename, always compute the hash to trigger updates when code changes. The source_code_hash field should change whenever your code changes to force Lambda to update. Use:
- filebase64sha256() for local files
- source_code_hash = var.source_hash when building externally
This ensures Lambda stays in sync with your code changes.
Error: Error rendering template: template not found
How to fix "template not found" error in Terraform
Error: Error generating private key
How to fix 'Error generating private key' in Terraform
Error creating Kubernetes Service: field is immutable
How to fix "field is immutable" errors in Terraform
Error: Error creating local file: open: permission denied
How to fix "Error creating local file: permission denied" in Terraform
Error: line endings have changed from CRLF to LF
Line endings have changed from CRLF to LF in Terraform