opentofu/opentofu · error
The "remote" backend does not support the %q operation.
Error message
The "remote" backend does not support the %q operation.
What it means
The default branch of the operation dispatch switch in Remote.Operation (backend.go:711): op.Type is something other than Plan, Apply, or Refresh (refresh is special-cased with its own message). This is a programming-error path — the CLI itself never routes other operation types here, so embedders or custom frontends calling backend.Operation with an unexpected OperationType hit it.
Source
Thrown at internal/backend/remote/backend.go:711
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,
}
// stopCtx wraps the context passed in, and is used to signal a graceful Stop.
stopCtx, stop := context.WithCancel(ctx)
runningOp.Stop = stop
View on GitHub (pinned to 3561785c48)
Solutions
- Set op.Type explicitly to backend.OperationTypePlan or OperationTypeApply before calling Operation
- If you maintain a caller of backend.Operation, validate/whitelist the operation type before dispatch
- For refresh-style needs use OperationTypePlan/Apply with refresh-only semantics instead
- Return a clear error to your own users rather than forwarding unknown types into the backend
Example fix
// before
op := &backend.Operation{Type: backend.OperationType(0)} // zero/unknown
_, err := b.Operation(ctx, op) // -> "does not support the \"%!z(...)\" operation."
// after
op := &backend.Operation{Type: backend.OperationTypePlan}
_, err := b.Operation(ctx, op) Defensive patterns
Strategy: validation
Validate before calling
// whitelist operation types before calling backend.Operation
func validOpType(t backend.OperationType) bool {
switch t {
case backend.OperationTypePlan, backend.OperationTypeApply, backend.OperationTypeRefresh:
return true
}
return false
}
if !validOpType(op.Type) {
return fmt.Errorf("unsupported operation type: %d", op.Type)
} Type guard
func isUnsupportedOpErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "does not support the") && strings.Contains(err.Error(), "operation")
} Try / catch
// treat as a programmer error: fail fast with the caller's own context
if _, err := b.Operation(ctx, op); err != nil {
if isUnsupportedOpErr(err) {
return fmt.Errorf("wrapper bug: op.Type=%d rejected by remote backend: %w", op.Type, err)
}
return err
} Prevention
- Always set Operation.Type explicitly; never rely on zero values
- Unit-test wrappers with every OperationType you forward
- When adding new OperationType constants, grep backend implementations for switch coverage
When it happens
Trigger: A Go program obtains a backend.Remote and calls Operation with an op.Type value outside the handled set (custom or newly added operation type constants), or a zero-value Operation struct whose Type was never set.
Common situations: Tooling built on the backend package that forwards user-supplied operation strings; refactors where a new OperationType constant is introduced without updating the remote backend switch; unit tests constructing bare Operation values.
Related errors
- The "refresh" operation is not supported when using the "r
- Unknown or unexpected cost estimate state: %s
- %s errored.
- %s hard failed.
- %s soft failed. %s
AI-assisted analysis of opentofu/opentofu@3561785c48 (2026-08-15).
Data as JSON: /api/errors/7ea29d109c4182fe.
Report an issue: GitHub.