The 'Invalid multi-line string' error occurs when you attempt to split quoted strings across multiple lines in Terraform. Quoted strings must remain on a single line—use heredoc syntax or escape sequences for multi-line content.
Terraform's configuration language requires that quoted strings (enclosed in double quotes) be contained entirely on a single line. Attempting to split a quoted string across multiple lines—like starting a string on one line with an opening quote and continuing it on the next line—violates this syntax rule. The error message typically says: 'Quoted strings may not be split over multiple lines. To produce a multi-line string, either use the \n escape to represent a newline character or use the heredoc multi-line template syntax.' This is a parsing error that Terraform encounters during the configuration validation phase. The parser cannot correctly interpret strings that span multiple lines when they're using quoted string syntax, as it expects the closing quote to appear on the same line as the opening quote.
The Terraform error message will show you the exact line number where the parse error occurred. Look at that line and the lines around it in your .tf file to find the problematic string.
# INCORRECT - String split across lines:
local_file = "/path/to/file/that/
contains/multiple/paths"
# This will trigger: Error: Invalid multi-line stringUse your editor's line numbering or the error message line reference to quickly locate the issue. The problematic string will be the one using quotes that extends beyond a single line.
Terraform offers three ways to handle content that spans multiple lines. Choose the one that fits your use case:
Option 1: Use heredoc syntax (recommended for true multi-line strings)
user_data = <<EOF
#!/bin/bash
echo 'Hello World'
echo 'Installing packages'
apt-get update
EOFHeredoc syntax uses <<IDENTIFIER to start and must have the identifier on its own line to end. Content between is literal (no quote escaping needed).
Option 2: Use indented heredoc for cleaner formatting
script_content = <<-EOT
#!/bin/bash
echo 'This is indented'
echo 'Terraform will dedent it automatically'
EOTThe <<- variant allows you to indent the closing marker and content, making code more readable.
Option 3: Use escape sequences for simple line breaks
message = "Line 1\nLine 2\nLine 3"
description = "This is a long string that needs a break\nwith explicit newline characters"Use \n for newlines, \t for tabs, and \\ for literal backslashes within a single-line quoted string.
Take your problematic multi-line string and rewrite it using one of the three approaches above.
Example conversion:
Before (incorrect):
resource "aws_instance" "example" {
user_data = "#!/bin/bash
edit configuration file
install software"
}After (correct - using heredoc):
resource "aws_instance" "example" {
user_data = <<EOF
#!/bin/bash
edit configuration file
install software
EOF
}Or after (correct - using escape sequences):
resource "aws_instance" "example" {
user_data = "#!/bin/bash\nedit configuration file\ninstall software"
}Choose heredoc for readability when dealing with scripts or large blocks of text. Use escape sequences for shorter strings where inline text is acceptable.
When using heredoc, be aware of how special characters are handled:
In quoted strings (with escape sequences):
- \n → newline
- \t → tab
- \" → literal quote
- \\ → literal backslash
- ${...} → interpolation (use \${...} to escape)
- %{...} → directives (use %{~ ...} to strip whitespace)
In heredoc strings:
config = <<EOC
No escape sequences needed here
Backslashes are literal: C:\\Users\\Data
But interpolation still works: ${var.name}
End marker EOC must be at line start
EOCHeredoc preserves literal backslashes and spaces, making them ideal for configuration files, scripts, and data that shouldn't be escaped. Use <<- if you want to indent the closing marker.
After fixing the string syntax, validate that your configuration is now correct:
# Validate the syntax
terraform validate
# Check for other issues and format
terraform fmt -recursive
# Generate a plan to ensure resources are understood correctly
terraform planThe terraform validate command will parse all your .tf files and report any remaining syntax errors. If you see 'Success! The configuration is valid', the multi-line string error is resolved. If you still get parsing errors, review the error line number and apply the same fix to any other problematic strings.
When working with complex multi-line content like JSON, YAML, or shell scripts, heredoc is typically the best choice because it avoids the need to escape quotes and special characters. For JSON/YAML, consider using jsonencode() or yamlencode() functions with variables rather than inline strings. If you're generating Terraform code (using tools like Terragrunt or CDK for Terraform), ensure the code generator is outputting valid HCL syntax. Interpolation like ${var.example} continues to work inside heredoc blocks unless you prefix with ~ for directive-style stripping. When copying code from GitHub or documentation, be careful to preserve the original line structure—web browsers sometimes mangle whitespace and line breaks. For reusable multi-line content across multiple resources, consider storing the content in variables or local values, then reference them. This improves maintainability and makes the syntax cleaner.
Error: Error installing helm release: cannot re-use a name that is still in use
How to fix "release name in use" error in Terraform with Helm
Error: Error creating GKE Cluster: BadRequest
BadRequest error creating GKE cluster in Terraform
Error: External program failed to produce valid JSON
External program failed to produce valid JSON
Error: Unsupported argument in child module call
How to fix "Unsupported argument in child module call" in Terraform
Error: network is unreachable
How to fix "network is unreachable" in Terraform