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

  1. Read the joined error titles — they echo the TFC/HCP API error text and identify the failing field/constraint.
  2. Fix the specific config value or API argument the API rejected, then retry.
  3. 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

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


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/b593aa250fca7bc6. Report an issue: GitHub.