The local-exec provisioner runs commands on the machine executing Terraform, not on the target resources. This introduces unique error patterns around command execution, permissions, and environment handling.
Introduction
This article covers troubleshooting steps and solutions for How to Fix Terraform Local-Exec Errors. The error typically occurs in production environments and can cause service disruptions if not addressed promptly.
Symptoms
Common error messages include:
Error: Error running command: exit status 1
Error: command not found: ./script.sh
Error: Permission denied: cannot execute
Error: environment variable not found: AWS_ACCESS_KEYError: Error running command './deploy.sh': exit status 1resource "null_resource" "deploy" {
provisioner "local-exec" {
command = "./deploy.sh" # Script exits with non-zero
}
}Common Causes
- Configuration misconfiguration
- Missing or incorrect credentials
- Network connectivity issues
- Version compatibility problems
- Resource exhaustion or limits
- Permission or access denied
Step-by-Step Fix
- 1.Check logs for specific error messages
- 2.Verify configuration settings
- 3.Test network connectivity
- 4.Review recent changes
- 5.Apply corrective action
- 6.Verify the fix
Understanding Local-Exec Errors
Common local-exec errors:
``
Error: Error running command: exit status 1
Error: command not found: ./script.sh
Error: Permission denied: cannot execute
Error: environment variable not found: AWS_ACCESS_KEY
Issue 1: Command Exit Code Failures
Commands return non-zero exit codes.
Error Example:
``
Error: Error running command './deploy.sh': exit status 1
Root Cause:
``hcl
resource "null_resource" "deploy" {
provisioner "local-exec" {
command = "./deploy.sh" # Script exits with non-zero
}
}
Solution:
Debug the command:
``bash
# Run the command manually
./deploy.sh
echo $? # Check exit code
Add error handling in the script: ```hcl resource "null_resource" "deploy" { provisioner "local-exec" { command = <<-EOT set -e # Exit on error ./deploy.sh || { echo "Deploy failed, but continuing" exit 0 # Don't fail Terraform } EOT
on_failure = continue # Alternative: don't fail on error } } ```
Better script with proper error handling: ```bash #!/bin/bash set -e
log() { echo "[$(date)] $1" }
log "Starting deployment"
# Check prerequisites if ! command -v aws &> /dev/null; then log "ERROR: AWS CLI not found" exit 1 fi
# Main deployment log "Deploying application..." aws s3 sync ./dist s3://my-bucket/app/
log "Deployment complete" ```
Issue 2: Command Not Found
Specified command or script doesn't exist.
Error Example:
``
Error: Error running command './scripts/deploy.sh':
fork/exec ./scripts/deploy.sh: no such file or directory
Solution:
Verify path and file existence: ```bash # Check if script exists ls -la ./scripts/deploy.sh
# Check working directory pwd ```
Use absolute paths: ```hcl resource "null_resource" "deploy" { provisioner "local-exec" { # Use absolute path command = "${path.module}/scripts/deploy.sh"
# Or use path.root for repository root # command = "${path.root}/scripts/deploy.sh" } } ```
Or use inline commands: ```hcl resource "null_resource" "deploy" { provisioner "local-exec" { command = <<-EOT chmod +x ${path.module}/scripts/deploy.sh ${path.module}/scripts/deploy.sh EOT
# Or run directly with interpreter interpreter = ["bash", "-c"] } } ```
Issue 3: Permission Denied
Cannot execute script due to permission issues.
Error Example:
``
Error: Error running command './script.sh':
fork/exec ./script.sh: permission denied
Solution:
Fix script permissions:
``hcl
resource "null_resource" "deploy" {
provisioner "local-exec" {
command = <<-EOT
chmod +x ${path.module}/scripts/deploy.sh
${path.module}/scripts/deploy.sh
EOT
}
}
Or use interpreter:
``hcl
resource "null_resource" "deploy" {
provisioner "local-exec" {
command = "${path.module}/scripts/deploy.sh"
interpreter = ["bash", "-c"]
}
}
Or specify interpreter inline:
``hcl
resource "null_resource" "deploy" {
provisioner "local-exec" {
interpreter = ["python3", "-c"]
command = <<-EOT
import subprocess
subprocess.run(['./deploy.sh'])
EOT
}
}
Issue 4: Environment Variable Issues
Required environment variables missing or incorrect.
Error Example:
``
Error: Error running command 'aws s3 ls':
An error occurred (AccessDenied) when calling the ListBuckets operation
Solution:
Pass environment variables explicitly: ```hcl resource "null_resource" "deploy" { provisioner "local-exec" { command = "aws s3 sync ./dist s3://${var.bucket_name}/"
environment = { AWS_ACCESS_KEY_ID = var.aws_access_key AWS_SECRET_ACCESS_KEY = var.aws_secret_key AWS_REGION = var.aws_region
# Custom variables APP_VERSION = var.app_version DEPLOY_ENV = terraform.workspace } } } ```
Use Terraform outputs: ```hcl resource "null_resource" "configure" { provisioner "local-exec" { command = "./configure.sh"
environment = { INSTANCE_IP = aws_instance.web.public_ip INSTANCE_ID = aws_instance.web.id DB_ENDPOINT = aws_db_instance.main.endpoint } } } ```
Issue 5: Working Directory Problems
Commands run from wrong directory.
Error Example:
``
Error: Error running command './build.sh':
Cannot find 'src/' directory
Solution:
Specify working directory: ```hcl resource "null_resource" "build" { provisioner "local-exec" { command = "./build.sh" working_dir = path.module # Module directory
# Or specify absolute path # working_dir = "/home/user/project" } } ```
Handle directory changes in command:
``hcl
resource "null_resource" "build" {
provisioner "local-exec" {
command = <<-EOT
cd ${path.module}/src
npm install
npm run build
EOT
}
}
Issue 6: Output Parsing Errors
Cannot parse command output correctly.
Error Example:
``
Error: Error running command 'get-value.sh':
Expected JSON output but got plain text
Solution:
Use jq for JSON parsing: ```hcl resource "null_resource" "extract_value" { provisioner "local-exec" { command = <<-EOT # Ensure JSON output output=$(get-value.sh --format json)
# Extract specific field value=$(echo "$output" | jq -r '.value')
# Save for later use echo "$value" > ${path.module}/output.txt EOT } }
# Read the output file for use in Terraform locals { extracted_value = file("${path.module}/output.txt") } ```
Better approach using external data source: ```hcl data "external" "get_value" { program = ["bash", "-c", "get-value.sh --format json"] }
output "value" { value = data.external.get_value.result.value } ```
Issue 7: Long-Running Command Timeout
Commands take longer than Terraform expects.
Error Example:
``
Error: Error running command 'build-large-app.sh':
context deadline exceeded
Solution:
Handle long-running processes: ```hcl resource "null_resource" "long_build" { provisioner "local-exec" { command = <<-EOT # Run in background with output capture nohup ./build-large-app.sh > build.log 2>&1 &
# Wait for completion while ! grep "BUILD_COMPLETE" build.log; do sleep 10 if grep "BUILD_FAILED" build.log; then exit 1 fi done EOT
# Or use async tools # command = "./build-async.sh --timeout 3600" } } ```
Issue 8: Destroy Provisioner Timing
Commands run at wrong time during destroy.
Error Example:
``
Error: Destroy provisioner failed - resource already gone
Solution:
Handle destroy timing properly: ```hcl resource "null_resource" "cleanup" { provisioner "local-exec" { when = destroy command = <<-EOT # Use stored information for cleanup if [ -f "${path.module}/resource-info.txt" ]; then RESOURCE_ID=$(cat ${path.module}/resource-info.txt) ./cleanup.sh $RESOURCE_ID fi EOT
on_failure = continue # Don't fail Terraform if cleanup fails }
provisioner "local-exec" { when = create command = <<-EOT # Store resource information for later cleanup echo "${aws_instance.web.id}" > ${path.module}/resource-info.txt EOT } } ```
Issue 9: Multi-line Command Issues
Long commands fail to parse correctly.
Error Example:
``
Error: Error running command: unexpected EOF
Solution:
Use heredoc syntax properly: ```hcl resource "null_resource" "deploy" { provisioner "local-exec" { command = <<-EOT # Multi-line script set -e
echo "Starting deployment" ./prepare.sh ./deploy.sh --version ${var.app_version} ./verify.sh
echo "Deployment complete" EOT } } ```
Avoid inline continuation: ```hcl # Wrong - hard to read and prone to errors # command = "echo start && ./deploy.sh && echo done"
# Right - use heredoc command = <<-EOT echo "start" ./deploy.sh echo "done" EOT ```
Verification
Debug local-exec commands: ```bash # Enable debug logging export TF_LOG=DEBUG terraform apply
# Test commands manually in same environment cd $(terraform workspace show) ./your-script.sh ```
Check command output:
``bash
# Run terraform with verbose output
terraform apply -verbose
Prevention
- 1.Use absolute paths with
${path.module}or${path.root} - 2.Handle errors in scripts with proper exit codes
- 3.Pass credentials via
environmentblock, not command arguments - 4.Use heredoc syntax for multi-line commands
- 5.Add
on_failure = continuefor non-critical operations - 6.Use external data source instead of file outputs
- 7.Test commands manually before adding to Terraform
- 8.Avoid local-exec for critical operations - use cloud-native tools instead
Related Articles
- [Fix Fix Terraform API Token Issue in Terraform](fix-terraform-api-token)
- [Fix Terraform Apply Timeout - Resource Creation Hanging Indefinitely](fix-terraform-apply-timeout)
- [How to Fix Terraform AWS Provider Errors](fix-terraform-aws-provider)
- [Fix Fix Terraform Azure Backend Issue in Terraform](fix-terraform-azure-backend)
- [Fix Terraform Backend Configuration Error - State Backend Setup Failure](fix-terraform-backend-config-error)
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "How to Fix Terraform Local-Exec Errors", "description": "Learn to fix Terraform local-exec provisioner errors including command execution, script permissions, and output handling.", "url": "https://www.fixwikihub.com/fix-terraform-local-exec", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2025-11-17T00:04:11.114Z", "dateModified": "2025-11-17T00:04:11.114Z" } </script>