{"record":{"id":"dd062ccdf7b67ac7","repo":"hashicorp/terraform","slug":"error-uploading-state-w","errorCode":null,"errorMessage":"error uploading state: %w","messagePattern":"error uploading state: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/cloud/state.go","lineNumber":234,"sourceCode":"\n\tstateFile, err := statefile.Read(bytes.NewReader(buf.Bytes()))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read state: %w\", err)\n\t}\n\n\tov, err := jsonstate.MarshalOutputs(stateFile.State.RootOutputValues)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to translate outputs: %w\", err)\n\t}\n\tjsonStateOutputs, err := json.Marshal(ov)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to marshal outputs to json: %w\", err)\n\t}\n\n\terr = s.uploadState(s.lineage, s.serial, s.forcePush, buf.Bytes(), jsonState, jsonStateOutputs)\n\tif err != nil {\n\t\ts.stateUploadErr = true\n\t\treturn fmt.Errorf(\"error uploading state: %w\", err)\n\t}\n\t// After we've successfully persisted, what we just wrote is our new\n\t// reference state until someone calls RefreshState again.\n\t// We've potentially overwritten (via force) the state, lineage\n\t// and / or serial (and serial was incremented) so we copy over all\n\t// three fields so everything matches the new state and a subsequent\n\t// operation would correctly detect no changes to the lineage, serial or state.\n\ts.readState = s.state.DeepCopy()\n\ts.readLineage = s.lineage\n\ts.readSerial = s.serial\n\n\treturn nil\n}\n\n// ShouldPersistIntermediateState implements statemgr.IntermediateStateConditionalPersister\nfunc (s *State) ShouldPersistIntermediateState(info *statemgr.IntermediateStatePersistInfo) bool {\n\tif info.ForcePersist {\n\t\treturn true","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/cloud/state.go#L216-L252","documentation":"Thrown during PersistState when the uploadState method fails to push the serialized state (raw, JSON, and JSON outputs) to HCP Terraform / TFE via the StateVersions.Upload API. On failure, s.stateUploadErr is set to true, which intentionally prevents the workspace from being unlocked so that a subsequent apply cannot run against stale state. This is the primary network/authorization error for remote state persistence.","triggerScenarios":"Network failure or timeout during the state version upload HTTP request; invalid or expired API token; workspace locked by another run causing a 409 conflict; lineage/serial mismatch (concurrent modification); TFE server 5xx error; workspace permissions insufficient for the authenticated user; old TFE version lacking the Upload endpoint triggering the fallback path which also fails.","commonSituations":"Intermittent network connectivity to app.terraform.io or a self-hosted TFE instance; expired/rotated API tokens after credential management changes; two CI pipelines running apply concurrently against the same workspace; TFE instance under load returning 502/503; user with read-only workspace membership attempting apply.","solutions":["Check network connectivity and DNS resolution to your HCP Terraform / TFE endpoint","Verify the API token is valid and not expired (terraform login or TF_TOKEN / credentials)","Ensure no other process is applying to the same workspace concurrently (check the run queue and workspace lock)","Confirm the authenticated user/team has write permissions on the workspace","Retry the operation after a brief wait if the wrapped error indicates a transient 5xx","If on self-hosted TFE, check the TFE instance health and that the state version upload API is supported"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Before persisting, verify the TFE client can reach the workspace:\nctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\ndefer cancel()\nif _, err := tfeClient.Workspaces.Read(ctx, organization, workspaceName); err != nil {\n    return fmt.Errorf(\"pre-persist workspace check failed, upload would likely fail: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"// Retry PersistState for transient upload errors, but surface conflicts:\nbackoff := time.Second\nfor attempt := 0; attempt < 3; attempt++ {\n    err := stateMgr.PersistState(schemas)\n    if err == nil {\n        break\n    }\n    msg := err.Error()\n    if strings.Contains(msg, \"409\") || strings.Contains(msg, \"conflict\") {\n        return err // lineage/serial conflict — do NOT retry blindly\n    }\n    if isTransientError(msg) {\n        time.Sleep(backoff)\n        backoff *= 2\n        continue\n    }\n    return err\n}","preventionTips":["Ensure exactly one process applies to each workspace at a time (use CI workspace queueing or external locking)","Keep API tokens fresh and rotate them with overlap, not cut-over","Monitor HCP Terraform status page before large-scale apply operations","Verify workspace permissions include write access for the CI service account"],"tags":["network","state-persist","tfe","upload","authentication","locking","terraform"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}