hashicorp/terraform · error
target_platform for provisioner has to be either
Error message
target_platform for provisioner has to be either %s or %s
What it means
Returned by parseConnectionInfo when target_platform is a non-empty value that is neither 'unix' nor 'windows'. The field controls scp command quoting and default script_path; only two platforms are implemented. An empty value is defaulted to unix, so this fires only for an explicit, unrecognized non-empty value.
Solutions
- Set target_platform to "unix" or "windows" (or omit it to default to unix).
- Remove trailing/leading whitespace from the value.
- Use "windows" for WinRM targets and "unix" (or omit) for SSH/Linux/BSD targets.
Example fix
// before
connection {
host = aws_instance.win.public_ip
type = "winrm"
target_platform = "win"
}
// after
connection {
host = aws_instance.win.public_ip
type = "winrm"
target_platform = "windows"
} Defensive patterns
Strategy: validation
Validate before calling
# Before apply, validate target_platform is one of the allowed values:
# grep -RnE 'target_platform\s*=\s*"(?!unix|windows)' *.tf && echo bad || echo ok
# In HCL, drive it from a variable with a validation block:
variable "target_platform" {
type = string
default = "unix"
validation {
condition = contains(["unix", "windows"], var.target_platform)
error_message = "target_platform must be 'unix' or 'windows'."
}
} Type guard
// Go guard if constructing connection info directly:
func validTargetPlatform(p string) bool {
return p == "" || p == "unix" || p == "windows"
} Prevention
- Use 'unix' or 'windows' (or omit) for target_platform.
- Drive the value from a validated variable in reusable modules.
- Add an OPA/Sentinel policy rejecting unsupported platform values.
When it happens
Trigger: connection.target_platform set to a typo or unsupported value such as 'linux', 'macos', 'win', or 'unixx'. Any non-empty value that is not exactly 'unix' or 'windows' triggers it.
Common situations: Guessing 'linux' instead of 'unix'; using 'win' instead of 'windows'; copy-paste from non-Terraform docs; trailing whitespace in the value.
Related errors
- host for provisioner cannot be empty
- Cannot quote scp command, target platform unknown
- Cannot set both 'source' and 'content'
- connection type ' ' not supported
- invalid empty string in 'script'
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/a66426e01ee17fba.
Report an issue: GitHub.
Appendix: source
Thrown at internal/communicator/ssh/provisioner.go:203
// Check if host is empty.
// Otherwise return error.
if connInfo.Host == "" {
return nil, fmt.Errorf("host for provisioner cannot be empty")
}
// Format the host if needed.
// Needed for IPv6 support.
connInfo.Host = shared.IpFormat(connInfo.Host)
if connInfo.Port == 0 {
connInfo.Port = DefaultPort
}
// Set default targetPlatform to unix if it's empty
if connInfo.TargetPlatform == "" {
connInfo.TargetPlatform = TargetPlatformUnix
} else if connInfo.TargetPlatform != TargetPlatformUnix && connInfo.TargetPlatform != TargetPlatformWindows {
return nil, fmt.Errorf("target_platform for provisioner has to be either %s or %s", TargetPlatformUnix, TargetPlatformWindows)
}
// Choose an appropriate default script path based on the target platform. There is no single
// suitable default script path which works on both UNIX and Windows targets.
if connInfo.ScriptPath == "" && connInfo.TargetPlatform == TargetPlatformUnix {
connInfo.ScriptPath = DefaultUnixScriptPath
}
if connInfo.ScriptPath == "" && connInfo.TargetPlatform == TargetPlatformWindows {
connInfo.ScriptPath = DefaultWindowsScriptPath
}
if connInfo.Timeout != "" {
connInfo.TimeoutVal = safeDuration(connInfo.Timeout, DefaultTimeout)
} else {
connInfo.TimeoutVal = DefaultTimeout
}
// Default all bastion config attrs to their non-bastion counterparts
if connInfo.BastionHost != "" {
// Format the bastion host if needed.View on GitHub (pinned to d32a084675)