hashicorp/terraform · error
Failed to upload state to
Error message
Failed to upload state to %v: %v
What it means
Thrown by the remote client Put when writing or closing the state object writer fails. Put opens a NewWriter, optionally sets KMSKeyName, writes the data, and closes; any error in that sequence is wrapped with the state file URL.
Solutions
- Grant roles/storage.objectAdmin (must include objects.create and objects.update).
- If using kms_encryption_key, verify the key exists and the account has roles/cloudkms.cryptoKeyEncrypterDecrypter on it.
- Check bucket retention policy / object versioning settings.
- Retry transient upload failures; inspect the wrapped %v.
Example fix
// before — read-only role // after gsutil iam ch serviceAccount:terraform@proj.iam.gserviceaccount.com:roles/storage.objectAdmin gs://tf-state
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: verify the account can write to the bucket. // gsutil cp /tmp/probe gs://bucket/.writeprobe && gsutil rm gs://bucket/.writeprobe // If kms_encryption_key set: gcloud kms keys describe ... and check encrypt/decrypt IAM.
Try / catch
// Retry transient upload failures (5xx, connection reset).
for i := 0; i < 3; i++ {
err := put(data)
if err == nil { break }
if !isTransient(err) { return err }
} Prevention
- Grant roles/storage.objectAdmin plus, when KMS is used, roles/cloudkms.cryptoKeyEncrypterDecrypter.
- Check bucket retention/holding policies before writes.
- Run writes from hosts with stable, high-bandwidth connectivity.
When it happens
Trigger: stateFileWriter.Write or stateFileWriter.Close returns an error — insufficient storage.objects.create permission, KMS key name invalid or inaccessible, bucket is versioning-locked, network error on upload, or bucket quota exceeded.
Common situations: Service account can read but not write; kms_encryption_key references a disabled or deleted Cloud KMS key; bucket has retention policy preventing overwrite; large state upload exceeds per-request limits; transient 5xx on upload.
Related errors
- Failed to delete state file
- Failed to open state file at
- querying Cloud Storage failed
- Failed to read state file attrs from
- Failed to read state file from
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/a7125eb95ec26bf6.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/gcs/client.go:77
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
}
if _, err := stateFileWriter.Write(data); err != nil {
return err
}
return stateFileWriter.Close()
}()
if err != nil {
return diags.Append(fmt.Errorf("Failed to upload state to %v: %v", c.stateFileURL(), err))
}
return diags
}
func (c *remoteClient) Delete() tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
ctx := context.TODO()
if err := c.stateFile().Delete(ctx); err != nil {
return diags.Append(fmt.Errorf("Failed to delete state file %v: %v", c.stateFileURL(), err))
}
return diags
}
// Lock writes to a lock file, ensuring file creation. Returns the generation
// number, which must be passed to Unlock().View on GitHub (pinned to d32a084675)