{"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/c9def3e214014c1188faabfc4a5bde5095139765/internal/builtin/provisioners/remote-exec/resource_provisioner.go#L203-L239","documentation":"Returned by the script-reading helper in remote-exec at resource_provisioner.go:221 when os.Open(s) fails for one of the local script paths declared in scripts = [...]. The %s is the offending path and %v the OS error. Open handles are closed before returning, so this is a clean early failure before any remote activity.","triggerScenarios":"A remote-exec provisioner with scripts = [\"./run.sh\"] where the file does not exist, is unreadable, or the path is wrong relative to the Terraform working directory.","commonSituations":"Relative path resolved against the wrong cwd; script file not committed to the repo; file permissions deny the Terraform process; typo in the path.","solutions":["Use an absolute path or verify the path resolves relative to the Terraform configuration directory.","Ensure the script file exists in the repo/workspace and is readable.","Check file permissions (chmod +r) for the user running Terraform."],"exampleFix":"// before\nprovisioner \"remote-exec\" { scripts = [\"scripts/setup.sh\"] } // Failed to open script\n\n// after\nprovisioner \"remote-exec\" { scripts = [\"${path.module}/scripts/setup.sh\"] }","handlingStrategy":"validation","validationCode":"// Validate every script path in the provisioner config before running.\nfor _, s := range scripts {\n    if _, err := os.Stat(s); err != nil {\n        return fmt.Errorf(\"script %q missing: %w\", s, err)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use ${path.module}/... for script paths so they resolve regardless of cwd.","Commit script files to the repo and run terraform fmt/validate in CI."],"tags":["terraform","remote-exec","filesystem","scripts","path"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}