hashicorp/terraform · error

failed checking for existing remote state

Error message

failed checking for existing remote state: %s

What it means

Thrown by the cloud state writer when s.refreshState() fails during the 'no prior state known' branch. Before writing a brand-new state snapshot, the backend refreshes to check for an existing snapshot it should update; if that refresh read fails, the write is aborted to avoid clobbering or duplicating state.

Solutions

  1. Verify the token's team has 'State Versions: Read' (and Write) on the workspace.
  2. Re-run `terraform login` if the token may have expired.
  3. Retry the apply — refreshState is a transient read that often clears on retry.
  4. Inspect the underlying %s cause: storage errors point to TFE backend config, auth errors to token/permissions.
  5. Confirm the workspace's state storage backend is healthy.
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: confirm read access to current remote state.
if err := s.refreshState(); err != nil {
    return fmt.Errorf("preflight state read failed: %w", err)
}

Try / catch

if err := s.refreshState(); err != nil {
    return fmt.Errorf("failed checking for existing remote state: %s", err)
}

Prevention

When it happens

Trigger: refreshState reads the current remote state over the TFE state API; it errors on auth failure, network/transport error, 5xx, or a corrupted/unreadable current state object. The error is wrapped (non-%w, plain %s) into this message.

Common situations: First apply to a workspace whose state backend has a permission issue; token lost read access to state mid-run; TFE state storage (S3/etc.) misconfigured or temporarily unavailable; network blip during the pre-write read.

Related errors


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

Appendix: source

Thrown at internal/cloud/state.go:186

	log.Printf("[DEBUG] cloud/state: state read serial is: %d; serial is: %d", s.readSerial, s.serial)
	log.Printf("[DEBUG] cloud/state: state read lineage is: %s; lineage is: %s", s.readLineage, s.lineage)

	if s.readState != nil {
		lineageUnchanged := s.readLineage != "" && s.lineage == s.readLineage
		serialUnchanged := s.readSerial != 0 && s.serial == s.readSerial
		stateUnchanged := statefile.StatesMarshalEqual(s.state, s.readState)
		if stateUnchanged && lineageUnchanged && serialUnchanged {
			// If the state, lineage or serial haven't changed at all then we have nothing to do.
			return nil
		}
		s.serial++
	} else {
		// We might be writing a new state altogether, but before we do that
		// we'll check to make sure there isn't already a snapshot present
		// that we ought to be updating.
		err := s.refreshState()
		if err != nil {
			return fmt.Errorf("failed checking for existing remote state: %s", err)
		}
		log.Printf("[DEBUG] cloud/state: after refresh, state read serial is: %d; serial is: %d", s.readSerial, s.serial)
		log.Printf("[DEBUG] cloud/state: after refresh, state read lineage is: %s; lineage is: %s", s.readLineage, s.lineage)

		if s.lineage == "" { // indicates that no state snapshot is present yet
			lineage, err := uuid.GenerateUUID()
			if err != nil {
				return fmt.Errorf("failed to generate initial lineage: %v", err)
			}
			s.lineage = lineage
			s.serial++
		}
	}

	f := statefile.New(s.state, s.lineage, s.serial)

	var buf bytes.Buffer
	err := statefile.Write(f, &buf)

View on GitHub (pinned to d32a084675)