{"record":{"id":"57b27584b111c5d9","repo":"hashicorp/terraform","slug":"error-uploading-state-v","errorCode":null,"errorMessage":"error uploading state: %v","messagePattern":"error uploading state: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote/backend_state.go","lineNumber":156,"sourceCode":"\t}\n\n\t// If we have a run ID, make sure to add it to the options\n\t// so the state will be properly associated with the run.\n\tif r.runID != \"\" {\n\t\toptions.Run = &tfe.Run{ID: r.runID}\n\t}\n\n\t// Create the new state.\n\t// Create the new state.\n\t_, err = r.client.StateVersions.Upload(ctx, r.workspace.ID, options)\n\tif errors.Is(err, tfe.ErrStateVersionUploadNotSupported) {\n\t\t// Create the new state with content included in the request (Terraform Enterprise v202306-1 and below)\n\t\tlog.Println(\"[INFO] Detected that state version upload is not supported. Retrying using compatibility state upload.\")\n\t\treturn diags.Append(r.uploadStateFallback(ctx, stateFile, state, o))\n\t}\n\tif err != nil {\n\t\tr.stateUploadErr = true\n\t\treturn diags.Append(fmt.Errorf(\"error uploading state: %v\", err))\n\t}\n\n\treturn nil\n}\n\n// Delete the remote state.\nfunc (r *remoteClient) Delete() tfdiags.Diagnostics {\n\tvar diags tfdiags.Diagnostics\n\terr := r.client.Workspaces.Delete(context.Background(), r.organization, r.workspace.Name)\n\tif err != nil && err != tfe.ErrResourceNotFound {\n\t\treturn diags.Append(fmt.Errorf(\"error deleting workspace %s: %v\", r.workspace.Name, err))\n\t}\n\n\treturn nil\n}\n\n// EnableForcePush to allow the remote client to overwrite state\n// by implementing remote.ClientForcePusher","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote/backend_state.go#L138-L174","documentation":"Emitted by remoteClient.Put (backend_state.go:154-157) when the primary StateVersions.Upload fails for any reason other than ErrStateVersionUploadNotSupported (which diverts to the compatibility path). It sets r.stateUploadErr=true so the workspace lock is intentionally retained to block applies until consistent state is restored.","triggerScenarios":"The TFC/TFE Upload endpoint returns an error: 401/403 auth or permission, 409 lineage/serial conflict (state pushed by another process), 413 payload too large, MD5 mismatch, 5xx server error, or network failure.","commonSituations":"Two CI jobs racing to write the same workspace (serial conflict); expired token; state grew past server limits; transient TFC 5xx; MD5 mismatch from local state corruption; running apply while a concurrent plan/apply uploaded newer state.","solutions":["Inspect the wrapped %v: a serial/lineage conflict means a newer state exists remotely — run `terraform state pull`, reconcile, and re-push rather than forcing.","Use `-lock-timeout` and ensure only one writer per workspace to avoid serial races.","Refresh the token (`terraform login`) if the cause is 401/403.","If the workspace is now stuck locked due to stateUploadErr, run `terraform force-unlock` only after confirming state consistency."],"exampleFix":"// before: concurrent writers caused serial conflict\nError: error uploading state: 409 Conflict: serial 12 already exists\n\n// after: serialize writes with locking\n$ terraform apply -lock-timeout=120s","handlingStrategy":"retry","validationCode":"// Preflight: confirm the remote serial/lineage so you can detect a conflict before upload.\nif cur, err := r.client.StateVersions.ReadCurrent(ctx, r.workspace.ID); err == nil && cur.Serial >= int64(stateFile.Serial) {\n    if !r.forcePush { return fmt.Errorf(\"remote serial %d >= local %d; refusing non-force upload\", cur.Serial, stateFile.Serial) }\n}","typeGuard":null,"tryCatchPattern":"// Retry transient errors; surface conflicts distinctly so the operator reconciles state.\n_, err = r.client.StateVersions.Upload(ctx, r.workspace.ID, options)\nif errors.Is(err, tfe.ErrStateVersionUploadNotSupported) { return r.uploadStateFallback(ctx, stateFile, state, o) }\nif err != nil {\n    r.stateUploadErr = true\n    // do not unlock; return error so lock is retained\n}","preventionTips":["Serialize writes per workspace with `-lock-timeout` to avoid serial races.","Inspect the wrapped cause: 409 -> reconcile state, 401/403 -> refresh token, 5xx -> retry.","Only force-push (forcePush=true) when you understand the lineage/serial implications.","Run `terraform force-unlock` only after confirming state consistency post-failure."],"tags":["state","upload","network","concurrency","terraform-cloud","lock"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}