hashicorp/terraform · error

HTTP remote state endpoint requires auth

Error message

HTTP remote state endpoint requires auth

What it means

During Lock(), the state server returned 401 Unauthorized. The backend sent a request to lock_address with the configured LockMethod (default LOCK) and either no credentials or credentials the server rejected. Distinct from 403 (error 251) which means credentials were accepted but lacked permission.

Source

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

	if c.LockURL == nil {
		return "", nil
	}
	c.lockID = ""

	jsonLockInfo := info.Marshal()
	resp, err := c.httpRequest(c.LockMethod, c.LockURL, &jsonLockInfo, "lock")
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	switch resp.StatusCode {
	case http.StatusOK:
		c.lockID = info.ID
		c.jsonLockInfo = jsonLockInfo
		return info.ID, nil
	case http.StatusUnauthorized:
		return "", fmt.Errorf("HTTP remote state endpoint requires auth")
	case http.StatusForbidden:
		return "", fmt.Errorf("HTTP remote state endpoint invalid auth")
	case http.StatusConflict, http.StatusLocked:
		defer resp.Body.Close()
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			return "", &statemgr.LockError{
				Err: fmt.Errorf("HTTP remote state already locked, failed to read body"),
			}
		}
		existing := statemgr.LockInfo{}
		err = json.Unmarshal(body, &existing)
		if err != nil {
			return "", &statemgr.LockError{
				Err: fmt.Errorf("HTTP remote state already locked, failed to unmarshal body"),
			}
		}
		return "", &statemgr.LockError{

View on GitHub (pinned to c9def3e214)

Solutions

  1. Set username and password (or TF_HTTP_USERNAME/TF_HTTP_PASSWORD) to valid credentials for the state server.
  2. Confirm the credentials work with `curl -u "$TF_HTTP_USERNAME:$TF_HTTP_PASSWORD" -X LOCK <lock_address>`.
  3. If the server uses tokens instead of basic auth, ensure an auth proxy translates them or pick a backend that supports the server's scheme.

Example fix

// before
backend "http" {
  address = "https://state.corp/state"
}
// after
backend "http" {
  address  = "https://state.corp/state"
  username = var.state_user
  password = var.state_pass
}
Defensive patterns

Strategy: validation

Validate before calling

func validateAuth(user, pass string) error {
  if user == "" || pass == "" {
    return fmt.Errorf("state server requires username/password")
  }
  return nil
}

Prevention

When it happens

Trigger: username/password not set while the server requires basic auth; credentials wrong; TF_HTTP_USERNAME/TF_HTTP_PASSWORD unset in CI. Fires during `terraform apply` when the backend attempts to acquire the state lock.

Common situations: Switched state server to one requiring auth but did not update backend credentials; rotated password not propagated to CI secrets; basic-auth header stripped by a proxy.

Related errors


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