hashicorp/terraform · error

Failed to read state file attrs from %v: %v

Error message

Failed to read state file attrs from %v: %v

What it means

After reading the state body, Get() calls stateFile().Attrs(ctx) to fetch object metadata (specifically the MD5 for the remote.Payload). If that metadata call fails, the read is considered failed and surfaced here. The body succeeded but the attributes RPC did not.

Source

Thrown at internal/backend/remote-state/gcs/client.go:52

	ctx := context.TODO()
	stateFileReader, err := c.stateFile().NewReader(ctx)
	if err != nil {
		if err == storage.ErrObjectNotExist {
			return nil, diags
		} else {
			return nil, diags.Append(fmt.Errorf("Failed to open state file at %v: %v", c.stateFileURL(), err))
		}
	}
	defer stateFileReader.Close()

	stateFileContents, err := ioutil.ReadAll(stateFileReader)
	if err != nil {
		return nil, diags.Append(fmt.Errorf("Failed to read state file from %v: %v", c.stateFileURL(), err))
	}

	stateFileAttrs, err := c.stateFile().Attrs(ctx)
	if err != nil {
		return nil, diags.Append(fmt.Errorf("Failed to read state file attrs from %v: %v", c.stateFileURL(), err))
	}

	result := &remote.Payload{
		Data: stateFileContents,
		MD5:  stateFileAttrs.MD5,
	}

	return result, diags
}

func (c *remoteClient) Put(data []byte) tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics
	ctx := context.TODO()
	err := func() error {
		stateFileWriter := c.stateFile().NewWriter(ctx)
		if len(c.kmsKeyName) > 0 {
			stateFileWriter.KMSKeyName = c.kmsKeyName
		}

View on GitHub (pinned to c9def3e214)

Solutions

  1. Retry the terraform command; Attrs failures are usually transient.
  2. If persistent, check 'gsutil stat gs://<bucket>/<prefix>/<ws>.tfstate' to confirm the object still exists and metadata is readable.
  3. Investigate concurrent state deletion or a competing CI job writing/deleting the same workspace.
  4. Ensure the SA has 'storage.objects.get' which covers both body and metadata.

Example fix

# recover
terraform state pull   # retry
gsutil stat gs://bucket/prefix/default.tfstate   # confirm metadata readable
Defensive patterns

Strategy: retry

Try / catch

for attempt := 0; attempt < 3; attempt++ {
    _, diags := client.Get()
    if !diags.HasErrors() { break }
    if !strings.Contains(diags.Err().Error(), "attrs") { break }
    time.Sleep(backoff(attempt))
}

Prevention

When it happens

Trigger: The object was deleted between the NewReader and Attrs calls; transient GCS metadata API failure; IAM allows get object body but not get metadata (rare misconfiguration); object lock/hold returning attrs error.

Common situations: Race with another process deleting the state; transient GCS 5xx on the GET-metadata RPC; eventual-consistency surprise.

Related errors


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