opentofu/opentofu · error

The "refresh" operation is not supported when using the "r

Error message


The "refresh" operation is not supported when using the "remote" backend. Use "tofu apply -refresh-only" instead.

What it means

Returned by Remote.Operation (backend.go:707) when op.Type is backend.OperationTypeRefresh: the remote backend deliberately does not implement the standalone refresh operation because runs execute server-side in TFC/TFE. The message itself directs users to `tofu apply -refresh-only` instead.

Source

Thrown at internal/backend/remote/backend.go:707

		// Record that we're forced to run operations locally to allow the
		// command package UI to operate correctly
		b.forceLocal = true
		log.Printf("[DEBUG] Remote backend is delegating %s to the local backend", op.Type)
		return b.local.Operation(ctx, op)
	}

	// Set the remote workspace name.
	op.Workspace = w.Name

	// Determine the function to call for our operation
	var f func(context.Context, context.Context, context.Context, *backend.Operation, *tfe.Workspace) (*tfe.Run, error)
	switch op.Type {
	case backend.OperationTypePlan:
		f = b.opPlan
	case backend.OperationTypeApply:
		f = b.opApply
	case backend.OperationTypeRefresh:
		return nil, fmt.Errorf(
			"\n\nThe \"refresh\" operation is not supported when using the \"remote\" backend. " +
				"Use \"tofu apply -refresh-only\" instead.")
	default:
		return nil, fmt.Errorf(
			"\n\nThe \"remote\" backend does not support the %q operation.", op.Type)
	}

	// Lock
	b.opLock.Lock()

	// Build our running operation
	// the runningCtx is only used to block until the operation returns.
	runningCtx, done := context.WithCancel(context.Background())
	runningOp := &backend.RunningOperation{
		Context:   runningCtx,
		PlanEmpty: true,
	}

View on GitHub (pinned to 3561785c48)

Solutions

  1. Replace `tofu refresh` with `tofu apply -refresh-only` in scripts/CI for remote-backend configurations
  2. If you only want to update state without applying, use `tofu apply -refresh-only` and do not confirm any changes (or use -auto-approve with no changes pending)
  3. Switch to a backend that supports refresh (e.g. s3) if a standalone refresh is a hard requirement
  4. Audit pipelines for the refresh command when onboarding workspaces to the remote backend

Example fix

# before
tofu refresh

# after (remote backend)
tofu apply -refresh-only
Defensive patterns

Strategy: fallback

Validate before calling

// guard your wrapper before invoking the backend
func opSupportedForRemote(t backend.OperationType) bool {
  return t == backend.OperationTypePlan || t == backend.OperationTypeApply
}

Type guard

func isRefreshUnsupportedErr(err error) bool {
  return err != nil && strings.Contains(err.Error(), `"refresh" operation is not supported`)

Try / catch

if _, err := b.Operation(ctx, op); err != nil {
  if isRefreshUnsupportedErr(err) {
    // fall back: run apply with refresh-only semantics instead
  } else {
    return err
  }
}

Prevention

When it happens

Trigger: A caller invokes the Operation entry point with op.Type == OperationTypeRefresh — in practice, running `tofu refresh` (or terraform refresh) against a configuration whose backend is "remote" rather than "s3"/"local".

Common situations: Teams migrating from local/S3 backends to TFC keep refresh in scripts or CI pipelines; muscle-memory `tofu refresh` against a remote workspace; wrappers invoking refresh programmatically.

Related errors


AI-assisted analysis of opentofu/opentofu@3561785c48 (2026-08-15). Data as JSON: /api/errors/51898fdbaa22d6d0. Report an issue: GitHub.