hashicorp/terraform · warning
Ephemeral resources failed to Close during renew operations
Error message
Ephemeral resources failed to Close during renew operations
What it means
Appended to Close's diagnostics when an internal 10-second timeout elapses waiting for all ephemeral-resource renewal goroutines to drain (r.wg.Wait). It indicates an ephemeral resource provider whose Close (or a blocking renew call) did not return within the deadline, so Terraform is giving up waiting and reporting potential resource leakage. The comment notes it is often harmless but signals a misbehaving provider.
Solutions
- Identify which ephemeral resource did not close by correlating with surrounding log lines (the diag itself carries no per-resource context).
- Update the provider; a well-behaved provider must honour context cancellation in Close/Renew.
- File a provider bug if Close does not return promptly after context cancellation.
- If unavoidable, reduce the number of long-lived ephemeral resources or shorten their renewal windows so Close drains faster.
Example fix
n/a — indicates a provider-side defect; no caller-side code change fixes the underlying provider. Mitigate by updating the provider and correlating via logs.
Defensive patterns
Strategy: try-catch
Validate before calling
n/a — internal Close timeout; not preventable by caller input validation.
Type guard
func isEphemeralCloseTimeout(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to Close during renew")
} Try / catch
diags := resources.Close(ctx)
for _, d := range diags {
if strings.Contains(d.Description().Summary, "failed to Close during renew") {
// log provider misbehavior; correlate via surrounding log lines
log.Printf("[WARN] ephemeral provider did not close within 10s")
}
} Prevention
- Use providers whose Close/Renew honour context cancellation.
- Keep providers up to date; report deadlock bugs upstream.
- Correlate the diagnostic with provider log lines to identify the offending resource.
When it happens
Trigger: Resources.Close spawns a goroutine that waits on r.wg; the select at ephemeral_resources.go:185-194 fires the time.After(10*time.Second) branch before the wait-group reaches zero. Happens when a provider's Renew or Close on an ephemeral resource blocks indefinitely or very slowly.
Common situations: A provider bug where the Close/Renew RPC handler deadlocks or ignores context cancellation; an ephemeral resource backed by a remote system under heavy load; provider still performing I/O after Terraform asked it to close.
Related errors
- current outputs were not ready to be read within the…
- operation timed out
- operation timed out
- timeout - last error
- A managed resource address is required. Importing into a…
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/4bf6de2f0c71f4cc.
Report an issue: GitHub.
Appendix: source
Thrown at internal/resources/ephemeral/ephemeral_resources.go:193
// All renew loops should have returned, or else we're going to leak
// resources which could be continually renewing, or even interfering with
// the same resources during the next operation.
//
// Use an asynchronous check so we can timeout and report the problem.
done := make(chan int)
go func() {
r.wg.Wait()
close(done)
}()
select {
case <-done:
// OK!
case <-time.After(10 * time.Second):
// This is probably harmless a lot of time, but is also indicative of an
// ephemeral resource which would be misbehaving. The message isn't
// very helpful with no context, so we'll have to rely on correlating
// the problem via other log messages.
diags = diags.Append(errors.New("Ephemeral resources failed to Close during renew operations"))
}
return diags
}
type resourceInstanceInternal struct {
value cty.Value
configBody hcl.Body
impl ResourceInstance
renewCancel func()
renewDiags tfdiags.Diagnostics
renewMu sync.Mutex // hold when accessing renewCancel/renewDiags, and while actually renewing
}
// close halts this instance's asynchronous renewal loop, if any, and then
// calls Close on the resource instance's implementation object.
//View on GitHub (pinned to d32a084675)