Fix Terraform Error: CloudWatch Log Group Already Exists
Fix terraform CloudWatch Log Group ResourceAlreadyExistsException. Import orphaned log groups, prevent Lambda auto-creation
DevOps
Fix terraform local-exec provisioner failures. Debug exit codes, fix interpreter settings, handle working directories
# Test the command locally first
bash -c 'your-command-here'
echo $? # Check exit code (0 = success)Error: local-exec provisioner error
with aws_instance.web,
on main.tf line 25, in resource "aws_instance" "web":
25: provisioner "local-exec" {
Error running command 'kubectl apply -f k8s/': exit status 1Or:
Error: local-exec provisioner error
Error running command '/bin/sh -c "apt-get install -y jq"': exit status 100/bin/sh, but command needs bash# Run the exact command Terraform would run
/bin/sh -c 'your-command-here'
echo "Exit code: $?"If it fails locally, fix the command before putting it in Terraform.
provisioner "local-exec" {
# Default: ["/bin/sh", "-c"]
# For bash features (arrays, [[ ]], etc.):
interpreter = ["/bin/bash", "-c"]
command = <<-EOT
set -euo pipefail
if [[ -f config.json ]]; then
jq '.version' config.json
fi
EOT
}For Python:
provisioner "local-exec" {
interpreter = ["python3", "-c"]
command = "import json; print(json.dumps({'status': 'ok'}))"
}For Windows:
provisioner "local-exec" {
interpreter = ["PowerShell", "-Command"]
command = "Get-Process | Where-Object {$_.CPU -gt 100}"
}provisioner "local-exec" {
working_dir = "${path.module}/scripts"
command = "./deploy.sh"
}provisioner "local-exec" {
command = "ansible-playbook -i '${self.public_ip},' playbook.yml"
environment = {
ANSIBLE_HOST_KEY_CHECKING = "False"
ENV_NAME = terraform.workspace
DB_ENDPOINT = aws_db_instance.main.endpoint
}
}provisioner "local-exec" {
command = "curl -X POST https://slack.webhook.url -d '{\"text\": \"Deploy complete\"}'"
on_failure = continue # Don't fail the resource if Slack notification fails
}on_failure options:
fail (default) — resource creation failscontinue — log the error but continueprovisioner "local-exec" {
interpreter = ["/bin/bash", "-c"]
command = <<-EOT
set -euo pipefail # Exit on error, undefined vars, pipe failures
echo "Waiting for instance to be ready..."
for i in $(seq 1 30); do
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no \
ubuntu@${self.public_ip} 'echo ready' 2>/dev/null; then
echo "Instance is ready"
exit 0
fi
echo "Attempt $i/30 - waiting..."
sleep 10
done
echo "ERROR: Instance not ready after 5 minutes"
exit 1
EOT
}HashiCorp recommends avoiding provisioners when possible:
# ❌ Provisioner
provisioner "local-exec" {
command = "aws s3 cp config.json s3://my-bucket/"
}
# ✅ Native resource
resource "aws_s3_object" "config" {
bucket = "my-bucket"
key = "config.json"
source = "config.json"
}# ❌ Provisioner for user data
provisioner "remote-exec" {
inline = ["apt-get update && apt-get install -y nginx"]
}
# ✅ cloud-init user data
resource "aws_instance" "web" {
user_data = <<-EOF
#!/bin/bash
apt-get update && apt-get install -y nginx
EOF
}# Enable debug logging to see the full command output
export TF_LOG=DEBUG
terraform apply 2>&1 | grep -A 20 "local-exec"Local-exec provisioner errors mean the command returned a non-zero exit code. Test the command locally first, set the correct interpreter (bash vs sh), pass required environment variables, and use on_failure = continue for non-critical scripts. When possible, replace provisioners with native Terraform resources or cloud-init user data.
Fix terraform CloudWatch Log Group ResourceAlreadyExistsException. Import orphaned log groups, prevent Lambda auto-creation
Fix terraform import errors when a resource already exists in state. Covers state rm, state show, reimport workflow, import blocks
Fix terraform too many command line arguments errors. Correct -var syntax, quote values with spaces, and learn proper Terraform CLI argument format for plan
Fix terraform invalid escape sequence errors. Double backslashes for Windows paths, use heredocs for regex, and learn all valid HCL escape sequences.