hashicorp/terraform · error
operation timed out
Error message
operation timed out
What it means
Returned by the remote backend plan path (backend_plan.go:292) when the uploaded configuration version never reaches tfe.ConfigurationUploaded status within the polling loop. The backend uploads the config then polls ConfigurationVersions.Read; if uploaded is still false after all iterations, it wraps a plain 'operation timed out' error in generalError with the message 'Failed to upload configuration files'. The cause is usually TFE never acknowledging the upload (network, large config, slow/overloaded server), not an explicit wall-clock timeout.
Solutions
- Retry terraform plan — transient server/network issues are the most common cause.
- Check the TFE/HCP workspace UI for the configuration version status and any ingest errors.
- Reduce config size or use .terraformignore to skip large vendored files, then retry.
- Verify connectivity and proxies between your runner and the TFE hostname.
Defensive patterns
Strategy: retry
Try / catch
cv, err := b.uploadConfig(...)
if err != nil {
if strings.Contains(err.Error(), "operation timed out") {
// TFE did not acknowledge the upload in time; retry with backoff
return retryUpload()
}
return err
} Prevention
- Keep the config bundle small via .terraformignore.
- Verify TFE/HCP health and network connectivity before planning.
- Retry plan after transient ingest failures.
When it happens
Trigger: Running terraform plan with the 'remote' backend against a TFE/HCP server where the configuration-version upload completes the HTTP request but the server fails to flip the CV to ConfigurationUploaded within the poll window (the upload-then-poll loop in backend_plan.go).
Common situations: Very large config bundles that take longer than the poll budget to ingest. TFE sidecar/worker backpressure or outages. Network proxies that complete the upload but drop the status-read. A stale upload URL or an interrupted connection between upload and status read.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- operation timed out
- Error downloading state
- error loading workspace
- Error retrieving state
- approved using the UI or API
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/1d0e864c796a6f32.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote/backend_plan.go:292
case <-cancelCtx.Done():
log.Printf("[TRACE] backend/remote: operation cancelled while waiting for configuration status")
return nil, context.Canceled
case <-time.After(planConfigurationVersionsPollInterval):
log.Printf("[TRACE] backend/remote: reading configuration status")
cv, err = b.client.ConfigurationVersions.Read(stopCtx, cv.ID)
if err != nil {
return nil, generalError("Failed to retrieve configuration version", err)
}
if cv.Status == tfe.ConfigurationUploaded {
uploaded = true
}
}
}
if !uploaded {
return nil, generalError(
"Failed to upload configuration files", errors.New("operation timed out"))
}
log.Printf("[TRACE] backend/remote: configuration uploaded and ready")
runOptions := tfe.RunCreateOptions{
ConfigurationVersion: cv,
Refresh: tfe.Bool(op.PlanRefresh),
Workspace: w,
}
switch op.PlanMode {
case plans.NormalMode:
// okay, but we don't need to do anything special for this
case plans.RefreshOnlyMode:
runOptions.RefreshOnly = tfe.Bool(true)
case plans.DestroyMode:
runOptions.IsDestroy = tfe.Bool(true)
default:
// Shouldn't get here because we should update this for each newView on GitHub (pinned to d32a084675)