{"record":{"id":"2fe97fdf3c0a0b7c","repo":"hashicorp/terraform","slug":"failed-to-open-script-s-v","errorCode":null,"errorMessage":"Failed to open script '%s': %v","messagePattern":"Failed to open script '(.+?)': (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/builtin/provisioners/remote-exec/resource_provisioner.go","lineNumber":221,"sourceCode":"\t\t\t\treturn nil, errors.New(\"invalid null string in 'script'\")\n\t\t\t}\n\t\t\ts := script.AsString()\n\t\t\tif s == \"\" {\n\t\t\t\treturn nil, errors.New(\"invalid empty string in 'script'\")\n\t\t\t}\n\t\t\tscripts = append(scripts, s)\n\t\t}\n\t}\n\n\t// Open all the scripts\n\tvar fhs []io.ReadCloser\n\tfor _, s := range scripts {\n\t\tfh, err := os.Open(s)\n\t\tif err != nil {\n\t\t\tfor _, fh := range fhs {\n\t\t\t\tfh.Close()\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"Failed to open script '%s': %v\", s, err)\n\t\t}\n\t\tfhs = append(fhs, fh)\n\t}\n\n\t// Done, return the file handles\n\treturn fhs, nil\n}\n\n// runScripts is used to copy and execute a set of scripts\nfunc runScripts(ctx context.Context, o provisioners.UIOutput, comm communicator.Communicator, scripts []io.ReadCloser) error {\n\tretryCtx, cancel := context.WithTimeout(ctx, comm.Timeout())\n\tdefer cancel()\n\n\t// Wait and retry until we establish the connection\n\terr := communicator.Retry(retryCtx, func() error {\n\t\treturn comm.Connect(o)\n\t})\n\tif err != nil {","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/builtin/provisioners/remote-exec/resource_provisioner.go#L203-L239","documentation":"The remote-exec provisioner's collectScripts function fails to open a local script file referenced in the 'script' or 'scripts' attribute. After collecting script paths from the config, it iterates and calls os.Open on each. If any file cannot be opened, it closes all previously opened handles and returns this error.","triggerScenarios":"Using a remote-exec provisioner with 'script' or 'scripts' attributes pointing to a file that does not exist or is not readable. The os.Open call at resource_provisioner.go:216 fails with a filesystem error (ENOENT, EACCES, etc.).","commonSituations":"Typo in the script path relative to the Terraform working directory. Script file exists but has restrictive permissions (not readable by the Terraform process). Running 'terraform apply' from a different working directory than where the scripts are located. Script path contains unexpanded environment variables or ~.","solutions":["Verify the script file path is correct relative to the Terraform execution directory with `ls -la <path>`.","Ensure the script file is readable by the user running Terraform (check with `cat <path>`).","Use absolute paths or paths relative to the module root, not relative to your shell's cwd.","If using a list in 'scripts', validate every entry exists before running apply."],"exampleFix":"# before — relative path that may not resolve\nprovisioner \"remote-exec\" {\n  scripts = [\"~/deploy.sh\", \"../scripts/setup.sh\"]\n}\n\n# after — use path.module for reliable resolution\nprovisioner \"remote-exec\" {\n  scripts = [\"${path.module}/scripts/deploy.sh\", \"${path.module}/scripts/setup.sh\"]\n}","handlingStrategy":"validation","validationCode":"// Before running remote-exec, verify all script files exist\nfor _, scriptPath := range scriptPaths {\n    info, err := os.Stat(scriptPath)\n    if err != nil {\n        return fmt.Errorf(\"script file %s not found: %w\", scriptPath, err)\n    }\n    if info.IsDir() {\n        return fmt.Errorf(\"script path %s is a directory, not a file\", scriptPath)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use path.module-relative paths for scripts to ensure correct resolution regardless of cwd.","Verify script files exist with a pre-flight check or local-exec before the remote-exec provisioner.","Ensure script files are readable by the Terraform process user.","Avoid using ~ or environment variables in script paths; expand them beforehand."],"tags":["terraform","remote-exec","provisioner","filesystem","scripts","go"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}