Terraform failed because an external program exited with a non-zero status code. This commonly occurs with data sources, provisioners, or custom scripts that encounter errors during execution.
When Terraform executes an external program (via the external data source, local-exec provisioner, or similar), it expects the program to exit with status code 0 on success. Any non-zero exit code (1, 2, 126, 127, etc.) indicates the program encountered an error and Terraform halts the operation. The specific exit code provides clues about what went wrong: 1 is a general error, 126 typically means permission denied, 127 means command not found.
Run the external program directly from your command line in the same directory where you run Terraform, with the same arguments Terraform passes to it. This helps isolate whether the issue is with the program itself or its interaction with Terraform.
# Test the script manually
./path/to/script.sh arg1 arg2
echo $? # Check the exit codeIf it succeeds manually (exit code 0) but fails in Terraform, the issue is likely environmental.
Ensure your script explicitly exits with code 0 on success and uses proper error handling. For external data sources, the program must output valid JSON to stdout and only valid JSON—any warnings or debug output will cause parse failures.
#!/bin/bash
# Bad: no explicit exit code
result=$(some_command)
echo "{\"result\": \"$result\"}"
# Good: explicit exit handling
result=$(some_command)
if [ $? -ne 0 ]; then
echo "{\"error\": \"Command failed\"}" >&2
exit 1
fi
echo "{\"result\": \"$result\"}"
exit 0On Unix-based systems, external programs must have the executable bit set. Check and fix permissions as needed.
# Check current permissions
ls -l /path/to/script.sh
# Add executable bit if missing
chmod +x /path/to/script.shWindows scripts typically require no special permissions, but ensure the file extension matches the interpreter (e.g., .ps1 for PowerShell).
Exit code 127 typically means a command is not found. Verify that all commands your script uses are available in the Terraform execution environment, especially if using Terraform Cloud or running in containers.
# For Python: ensure modules are installed
python3 -c "import boto3"
# For CLI tools: verify they're in PATH
which gcloud
which aws
# In Terraform, explicitly use full paths
command = "${path.module}/scripts/deploy.sh"In Terraform Cloud, you may need to install dependencies as part of a provisioner or use a pre-built image.
If using local-exec or remote-exec provisioners, use the on_failure setting to choose between stopping on error or continuing. This won't fix the underlying program failure, but lets you control Terraform's behavior.
provisioner "local-exec" {
command = "./deploy.sh"
on_failure = continue # Continue even if script fails
# or: on_failure = fail # Stop on failure (default)
}Note: If a creation provisioner fails, the resource is marked tainted and will be recreated on the next apply.
Set Terraform debug logging to see the full program output and error details.
# Enable TRACE level logging (most detailed)
export TF_LOG=TRACE
export TF_LOG_PATH=./terraform.log
terraform apply
# Review the log file
cat terraform.log | grep -i externalThe logs will show the exact program output, exit code, and any stderr messages, helping you identify the root cause.
Exit code 126 specifically indicates permission denied—this happens when the script lacks the executable bit or the Terraform process lacks permissions to execute it. Exit codes 1-125 are user-defined; check your script documentation for what each code means. For external data sources, remember that program output must be a pure JSON map (string keys and values only); any other output causes 'Unexpected External Program Results' errors. If using Terraform Cloud, the program must be available in that environment—many tools like gcloud or aws CLI require explicit installation. Long-running external programs (30+ minutes) can sometimes timeout and exit with a signal rather than a clean exit code.
Error: Error installing helm release: cannot re-use a name that is still in use
How to fix "release name in use" error in Terraform with Helm
Error: Error creating GKE Cluster: BadRequest
BadRequest error creating GKE cluster in Terraform
Error: External program failed to produce valid JSON
External program failed to produce valid JSON
Error: Unsupported argument in child module call
How to fix "Unsupported argument in child module call" in Terraform
Error: network is unreachable
How to fix "network is unreachable" in Terraform