hashicorp/terraform · error
error uploading state: %w
Error message
error uploading state: %w
What it means
Wraps any failure of StateVersions.Upload (or the compatibility StateVersions.Create fallback) at the end of PersistState when uploading a new state version to HCP Terraform/TFE. On failure it sets s.stateUploadErr=true, which makes the subsequent Unlock a no-op so the workspace stays locked and no unsafe change is applied until a good state is uploaded.
Source
Thrown at internal/cloud/state.go:234
stateFile, err := statefile.Read(bytes.NewReader(buf.Bytes()))
if err != nil {
return fmt.Errorf("failed to read state: %w", err)
}
ov, err := jsonstate.MarshalOutputs(stateFile.State.RootOutputValues)
if err != nil {
return fmt.Errorf("failed to translate outputs: %w", err)
}
jsonStateOutputs, err := json.Marshal(ov)
if err != nil {
return fmt.Errorf("failed to marshal outputs to json: %w", err)
}
err = s.uploadState(s.lineage, s.serial, s.forcePush, buf.Bytes(), jsonState, jsonStateOutputs)
if err != nil {
s.stateUploadErr = true
return fmt.Errorf("error uploading state: %w", err)
}
// After we've successfully persisted, what we just wrote is our new
// reference state until someone calls RefreshState again.
// We've potentially overwritten (via force) the state, lineage
// and / or serial (and serial was incremented) so we copy over all
// three fields so everything matches the new state and a subsequent
// operation would correctly detect no changes to the lineage, serial or state.
s.readState = s.state.DeepCopy()
s.readLineage = s.lineage
s.readSerial = s.serial
return nil
}
// ShouldPersistIntermediateState implements statemgr.IntermediateStateConditionalPersister
func (s *State) ShouldPersistIntermediateState(info *statemgr.IntermediateStatePersistInfo) bool {
if info.ForcePersist {
return trueView on GitHub (pinned to c9def3e214)
Solutions
- Re-run the operation; Terraform re-locks and re-uploads and transient network/5xx errors usually clear.
- Verify the API token is valid: terraform logout && terraform login.
- Confirm no other concurrent run is writing to the workspace.
- Check the HCP Terraform / Terraform Enterprise status page and retry.
- If a serial/lineage conflict persists, confirm who holds the lock and use terraform force-unlock only when safe.
Example fix
# before: stale / expired token causes upload failure terraform apply # -> error uploading state: ... # after: refresh credentials then retry terraform logout terraform login terraform apply
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight: token present and API reachable before attempting a write
if os.Getenv("TF_TOKEN_app_terraform_io") == "" && cfg.Token == "" {
return errors.New("no API token configured; run terraform login")
}
// Optionally ping the current-state endpoint to confirm connectivity/auth
if _, err := client.StateVersions.ReadCurrent(ctx, workspace.ID); err != nil && !errors.Is(err, tfe.ErrResourceNotFound) {
return fmt.Errorf("pre-upload check failed: %w", err)
} Try / catch
err := state.PersistState(schemas)
if err != nil && (isRetryable(err) || isTransientHTTP(err)) {
// re-lock and retry upload a bounded number of times
}
// NOTE: on failure the workspace is intentionally left locked; resolve the
// root cause or force-unlock deliberately rather than silently continuing. Prevention
- Keep the API token fresh (terraform login)
- Serialize runs per workspace to avoid serial/lineage conflicts
- Treat the held lock on upload failure as intentional safety, not a bug
When it happens
Trigger: PersistState calls uploadState and the StateVersions.Upload API returns an error: network failure, 401/403 auth, 409 lineage/serial conflict, 5xx server error, or workspace state rejecting a new version.
Common situations: Transient network blips, expired or revoked API token, two concurrent runs racing on the same workspace (serial/lineage mismatch), or an HCP/TFE outage/rate-limit.
Related errors
- consul lock was lost
- storage.NewClient() failed: %v
- Failed to upload state to %v: %v
- HTTP remote state endpoint requires auth
- HTTP remote state endpoint invalid auth
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/dd062ccdf7b67ac7.
Report an issue: GitHub.