hashicorp/terraform · error

HTTP error: %d

Error message

HTTP error: %d

What it means

The HTTP backend's Put() (state upload) received a status code other than 200, 201, or 204. These are the only success codes accepted for a POST/PUT state write; anything else (including redirects or 4xx/5xx) is reported as a generic HTTP error with the numeric code.

Source

Thrown at internal/backend/remote-state/http/client.go:241

		}
	*/

	var method string = "POST"
	if c.UpdateMethod != "" {
		method = c.UpdateMethod
	}
	resp, err := c.httpRequest(method, &base, &data, "upload state")
	if err != nil {
		return diags.Append(err)
	}
	defer resp.Body.Close()

	// Handle the error codes
	switch resp.StatusCode {
	case http.StatusOK, http.StatusCreated, http.StatusNoContent:
		return diags
	default:
		return diags.Append(fmt.Errorf("HTTP error: %d", resp.StatusCode))
	}
}

func (c *httpClient) Delete() tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics

	// Make the request
	resp, err := c.httpRequest("DELETE", c.URL, nil, "delete state")
	if err != nil {
		return diags.Append(err)
	}
	defer resp.Body.Close()

	// Handle the error codes
	switch resp.StatusCode {
	case http.StatusOK:
		return diags
	default:

View on GitHub (pinned to c9def3e214)

Solutions

  1. Use TF_LOG=DEBUG to capture the exact status code, then address the server-side cause for that code.
  2. If 405, set the correct `update_method` ("POST" or "PUT") matching what the state endpoint accepts.
  3. If 401/403, refresh or correct the username/password (or token) credentials for the state endpoint.
  4. If 413, raise the server's max body size limit to accommodate the state payload.
  5. If 409, the state is locked elsewhere; run `terraform force-unlock` or wait for the other run to finish.

Example fix

# before - server only accepts PUT but default POST is used
backend "http" {
  address = "https://state.example.com/tf"
}

# after - specify the method the endpoint accepts
backend "http" {
  address       = "https://state.example.com/tf"
  update_method = "PUT"
}
Defensive patterns

Strategy: validation

Validate before calling

# Probe the write endpoint with the method Terraform will use before running apply
curl -sS -o /dev/null -w "%{http_code}" -X "$METHOD" \
  -H "Content-Type: application/json" \
  -u "$USER:$PASS" --data-binary @small.json "$STATE_URL"
# expect 200, 201, or 204

Prevention

When it happens

Trigger: Calling Put() during `terraform apply`/`terraform destroy` to persist state, where the server responds with a non-success code such as 401, 403, 405 (method not allowed), 409 (conflict/lock), 413 (payload too large), or 500.

Common situations: The state endpoint does not allow POST/PUT (returns 405) when UpdateMethod is misconfigured; the server rejects large state bodies (413); authentication expired between read and write (401/403); a concurrent lock returns 409; a server error during write (500).

Related errors


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