TerraformPilot

DevOps

Fix Terraform Error - Null Resource Provisioner Failed

Fix null_resource provisioner failures in Terraform. Handle script errors, connection issues, triggers, and migrate to terraform_data for Terraform 1.4+.

LLuca Berton1 min read

Quick Answer

#

The script or command in your null_resource provisioner returned a non-zero exit code. Check the script for errors, verify connection settings for remote-exec, and consider using terraform_data (Terraform 1.4+) as a modern replacement.

The Error

#
Error: local-exec provisioner error
 
Error running command './deploy.sh': exit status 1
Error: null_resource.deploy (remote-exec): dial tcp 10.0.1.50:22: 
connection refused

What Causes This

#
  • Script error — the command/script failed (syntax error, missing dependency, wrong path)
  • Connection refused — SSH not ready, wrong IP, or security group blocks port 22
  • Missing triggersnull_resource runs on create only; changes don't trigger re-run
  • Working directory — script path is relative to where Terraform runs

How to Fix It

#

Solution 1: Debug the Script

#
resource "null_resource" "deploy" {
  provisioner "local-exec" {
    command = "bash -x ./deploy.sh"  # -x enables debug tracing
  }
}

Or test the script manually:

# Run the script directly to see the error
chmod +x deploy.sh
./deploy.sh

Solution 2: Fix Connection Issues (remote-exec)

#
resource "null_resource" "configure" {
  depends_on = [aws_instance.web]
 
  connection {
    type        = "ssh"
    host        = aws_instance.web.public_ip
    user        = "ubuntu"
    private_key = file("~/.ssh/deploy.pem")
    timeout     = "5m"  # Wait for instance to boot
  }
 
  provisioner "remote-exec" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y nginx",
    ]
  }
}

Solution 3: Use Triggers to Re-run

#
resource "null_resource" "deploy" {
  triggers = {
    app_version = var.app_version     # Re-runs when version changes
    script_hash = filemd5("deploy.sh") # Re-runs when script changes
  }
 
  provisioner "local-exec" {
    command = "./deploy.sh ${var.app_version}"
  }
}

Solution 4: Migrate to terraform_data (Terraform 1.4+)

#
# Modern replacement for null_resource
resource "terraform_data" "deploy" {
  triggers_replace = [var.app_version]
 
  provisioner "local-exec" {
    command = "./deploy.sh ${var.app_version}"
  }
}

Solution 5: Handle Failures Gracefully

#
resource "null_resource" "optional_step" {
  provisioner "local-exec" {
    command    = "./optional-cleanup.sh || true"  # Don't fail on error
    on_failure = continue  # Or use this
  }
}

Common Issues

#
ProblemFix
"command not found"Use full path or set PATH in environment
"permission denied"chmod +x script.sh
"connection refused"Wait for instance boot, check security groups
Script runs on create onlyAdd triggers to re-run on changes
Resource tainted after failureFix script, then terraform apply

Troubleshooting Checklist

#
  1. ✅ Does the script run successfully outside Terraform?
  2. ✅ Is the working directory correct?
  3. ✅ For remote-exec: is SSH accessible? (security groups, public IP, key)
  4. ✅ Are triggers configured to re-run when needed?
  5. ✅ Is the resource tainted from a previous failure?
#

Conclusion

#

Null resource provisioner failures are script/connection problems. Debug with bash -x, test scripts manually, use terraform_data for Terraform 1.4+, and add triggers so changes re-run the provisioner. For remote-exec, ensure SSH is accessible and the instance is fully booted.

#Terraform#Troubleshooting#DevOps#Error Fix#Infrastructure as Code

Share this article