hashicorp/terraform · error
strings.Join(errs, "\n")
Error message
strings.Join(errs, "\n")
What it means
This is the generic error factory in the cloud backend's HTTP-error decoder (cloud/backend_common.go:749). For TFE/HCP API responses that are not 401 (ErrUnauthorized) or 404 (ErrResourceNotFound), it decodes the JSON:api error payload and joins the per-error titles/details with newlines via strings.Join(errs, "\n"). You see this message when the API returned an error body with one or more titled errors (validation failures, conflicts, server errors).
Source
Thrown at internal/cloud/backend_common.go:749
return nil
}
var errs []string
var err error
switch r.StatusCode {
case 401:
return tfe.ErrUnauthorized
case 404:
return tfe.ErrResourceNotFound
}
errs, err = decodeErrorPayload(r)
if err != nil {
return err
}
return errors.New(strings.Join(errs, "\n"))
}
func decodeErrorPayload(r *http.Response) ([]string, error) {
// Decode the error payload.
var errs []string
errPayload := &jsonapi.ErrorsPayload{}
err := json.NewDecoder(r.Body).Decode(errPayload)
if err != nil || len(errPayload.Errors) == 0 {
return errs, errors.New(r.Status)
}
// Parse and format the errors.
for _, e := range errPayload.Errors {
if e.Detail == "" {
errs = append(errs, e.Title)
} else {
errs = append(errs, fmt.Sprintf("%s\n\n%s", e.Title, e.Detail))
}View on GitHub (pinned to d32a084675)
Solutions
- Read the joined error titles — they echo the TFC/HCP API error text and identify the failing field/constraint.
- Fix the specific config value or API argument the API rejected, then retry.
- If the error is transient (5xx, rate-limit), retry after a short backoff.
Defensive patterns
Strategy: try-catch
Try / catch
err := b.client.Workspaces.Update(ctx, org, name, opts)
if err != nil {
// cloud backend joins titled API errors with newlines
for _, line := range strings.Split(err.Error(), "\n") {
log.Printf("tfe api error: %s", line)
}
return err
} Prevention
- Parse the joined newline-delimited titles to find the failing field.
- Correct the rejected argument before retrying.
- Use exponential backoff for transient 5xx/429 bodies.
When it happens
Trigger: Any TFE/HCP API call made by the cloud backend that returns a non-2xx, non-401/404 response with a parseable JSON:api error payload — e.g. 422 workspace validation errors, 409 conflicts, 500s with structured errors — flows through decodeErrorPayload and is re-emitted as errors.Join of the titles.
Common situations: Workspace name/tag conflicts, invalid run options, rate limiting with a titled error body, malformed state uploads, plan/apply API validation rejections.
Related errors
- r.Status
- your version of Terraform Enterprise does not support key-va
- operation timed out
- error loading workspace: %w
- error loading variables: %w
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/b593aa250fca7bc6.
Report an issue: GitHub.