hashicorp/terraform · error
Error reading script
Error message
Error reading script: %s
What it means
Raised in UploadScript when bufio.Reader.Peek(2) fails to read the first two bytes of the script content. Peek fails when the underlying reader returns an error before any data (e.g. an empty/closed reader, a pipe whose writer end closed, or an upstream provisioner producing an I/O error). The shebang check needs those bytes to decide whether to prepend DefaultShebang.
Solutions
- Verify the script source is readable and non-empty before the provisioner runs (cat the file locally, or print the variable).
- For file-based scripts, confirm the path resolves under the module (use path.module / path.root).
- confirm `templatefile()` inputs exist and the template itself is valid.
- If using a data source for the script, ensure it returns content without error.
Example fix
// before
provisioner "remote-exec" {
inline = file("${path.module}/scripts/setup.sh") // file missing
}
// after
provisioner "remote-exec" {
inline = file("${path.module}/files/setup.sh") // correct path
} Defensive patterns
Strategy: validation
Validate before calling
# Confirm the script source is readable and non-empty before apply:
# test -s scripts/setup.sh && echo ok || echo 'missing or empty'
# In HCL, guard file() with a check variable if needed:
# variable "script_path" { type = string; validation {...} } Try / catch
// In Go feeding the script reader, peek ahead and fail with a clearer msg:
head := make([]byte, 2)
n, err := io.ReadFull(reader, head)
if err != nil && n == 0 {
return fmt.Errorf("script source produced no data; check path/template: %w", err)
} Prevention
- Reference scripts via path.module to keep them portable.
- Validate file existence with terraform console: fileexists(path.module.'/x.sh').
- Avoid piping from data sources that can return errors; check first.
When it happens
Trigger: An inline script passed via a broken variable reference, a file() call on a missing path, a template that evaluated to nothing, or a producer that errored/closed before yielding data. Most commonly the script source is malformed or empty beyond what Peek tolerates.
Common situations: file("${path.module}/script.sh") pointing at a non-existent file; templatefile producing an I/O error; a custom data source returning an error value used directly as the script; an empty inline script set with an expression that resolved to no bytes.
Related errors
- Error chmodding script file to 0777 in remote machine
- Error reading error message
- Failed to upload script
- Error chmodding script file to 0777 in remote machine
- Error creating temporary file for upload
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/3fbce8ad65611280.
Report an issue: GitHub.
Appendix: source
Thrown at internal/communicator/ssh/communicator.go:451
}
scpFunc := func(w io.Writer, stdoutR *bufio.Reader) error {
return scpUploadFile(targetFile, input, w, stdoutR, size)
}
cmd, err := quoteScpCommand([]string{"scp", "-vt", targetDir}, c.connInfo.TargetPlatform)
if err != nil {
return err
}
return c.scpSession(cmd, scpFunc)
}
// UploadScript implementation of communicator.Communicator interface
func (c *Communicator) UploadScript(path string, input io.Reader) error {
reader := bufio.NewReader(input)
prefix, err := reader.Peek(2)
if err != nil {
return fmt.Errorf("Error reading script: %s", err)
}
var script bytes.Buffer
if string(prefix) != "#!" && c.connInfo.TargetPlatform != TargetPlatformWindows {
script.WriteString(DefaultShebang)
}
script.ReadFrom(reader)
if err := c.Upload(path, &script); err != nil {
return err
}
if c.connInfo.TargetPlatform != TargetPlatformWindows {
var stdout, stderr bytes.Buffer
cmd := &remote.Cmd{
Command: fmt.Sprintf("chmod 0777 %s", path),
Stdout: &stdout,
Stderr: &stderr,
}View on GitHub (pinned to d32a084675)