hashicorp/terraform · warning

Ephemeral resources failed to Close during renew operations

Error message

Ephemeral resources failed to Close during renew operations

What it means

A diagnostic (not a sentinel) emitted by Resources.Close during teardown: after asynchronously closing all active ephemeral resource instances, it waits on the renew WaitGroup with a 10-second timeout. If the renew loops (and their Close calls) do not all drain within 10s, this warning-level diagnostic is appended to signal that one or more ephemeral resources likely leaked. The code comment notes this is 'probably harmless a lot of the time' but indicates a misbehaving provider.

Source

Thrown at internal/resources/ephemeral/ephemeral_resources.go:190

	// 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 c9def3e214)

Solutions

  1. Upgrade the provider — a Close/Renew hang is typically a provider-side bug that gets fixed in releases.
  2. Check TF_LOG for the provider process: look for the last Renew/Close RPC and whether the provider subprocess is still alive or crashed.
  3. Reduce the number/scope of ephemeral resources open at once, or shorten renew intervals if configurable, to lighten teardown pressure.
  4. If you author the provider, ensure Renew and Close return promptly and honor context cancellation.
  5. If purely cosmetic in your setup and resources do eventually clean up, you may safely proceed but report it as a provider issue.
Defensive patterns

Strategy: try-catch

Validate before calling

// No pre-check; this is a teardown-time diagnostic. Mitigate by ensuring
// provider Renew/Close are fast and context-aware before opening ephemeral resources.

Type guard

func isEphemeralCloseTimeout(diags tfdiags.Diagnostics) bool {
    return diags.Err() != nil && strings.Contains(diags.Err().Error(), "failed to Close during renew operations")
}

Try / catch

diags := resources.Close(ctx)
if isEphemeralCloseTimeout(diags) {
    // log and continue; report the provider as potentially leaking
    log.Printf("[WARN] ephemeral resources may have leaked: %s", diags.Err())
}

Prevention

When it happens

Trigger: Emitted at internal/resources/ephemeral/ephemeral_resources.go:190 when the select on the done channel loses to time.After(10*time.Second) in Resources.Close. The renew loops are started elsewhere (in the renew path of resourceInstanceInternal) and each holds r.wg.

Common situations: A provider whose Renew/Close RPC for an ephemeral resource blocks or is very slow (e.g. waiting on an external API). A provider that crashed after opening an ephemeral resource, leaving the renew loop stuck. Heavy load/network latency to the provider exceeding 10s. A provider bug that never returns from Close.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/4bf6de2f0c71f4cc. Report an issue: GitHub.