{"record":{"id":"562298781dd7a675","repo":"hashicorp/terraform","slug":"unsupported-operation-type-s-this-is-a-bug-in-t","errorCode":null,"errorMessage":"unsupported operation type: %s\n\nThis is a bug in Terraform and should be reported. The local backend\nis built-in to Terraform and should always support all operations.","messagePattern":"unsupported operation type: (.+?)\n\nThis is a bug in Terraform and should be reported\\. The local backend\nis built-in to Terraform and should always support all operations\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/backend/local/backend.go","lineNumber":314,"sourceCode":"// The given operation parameter will be merged with the ContextOpts on\n// the structure with the following rules. If a rule isn't specified and the\n// name conflicts, assume that the field is overwritten if set.\nfunc (b *Local) Operation(ctx context.Context, op *backendrun.Operation) (*backendrun.RunningOperation, error) {\n\tif op.View == nil {\n\t\tpanic(\"Operation called with nil View\")\n\t}\n\n\t// Determine the function to call for our operation\n\tvar f func(context.Context, context.Context, *backendrun.Operation, *backendrun.RunningOperation)\n\tswitch op.Type {\n\tcase backendrun.OperationTypeRefresh:\n\t\tf = b.opRefresh\n\tcase backendrun.OperationTypePlan:\n\t\tf = b.opPlan\n\tcase backendrun.OperationTypeApply:\n\t\tf = b.opApply\n\tdefault:\n\t\treturn nil, fmt.Errorf(\n\t\t\t\"unsupported operation type: %s\\n\\n\"+\n\t\t\t\t\"This is a bug in Terraform and should be reported. The local backend\\n\"+\n\t\t\t\t\"is built-in to Terraform and should always support all operations.\",\n\t\t\top.Type)\n\t}\n\n\t// Lock\n\tb.opLock.Lock()\n\n\t// Build our running operation\n\t// the runninCtx is only used to block until the operation returns.\n\trunningCtx, done := context.WithCancel(context.Background())\n\trunningOp := &backendrun.RunningOperation{\n\t\tContext: runningCtx,\n\t}\n\n\t// stopCtx wraps the context passed in, and is used to signal a graceful Stop.\n\tstopCtx, stop := context.WithCancel(ctx)","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/backend/local/backend.go#L296-L332","documentation":"Returned by Local.Operation when op.Type is not one of OperationTypeRefresh, OperationTypePlan, or OperationTypeApply. The message itself states this is a Terraform bug: the local backend is built-in and is expected to support every operation type, so reaching the default branch means the dispatch in core is broken or a new operation type was added without updating the local backend.","triggerScenarios":"Operation is called with an op.Type outside the three handled cases (e.g. OperationTypeInvalid, or a newly added operation type). In normal CLI flows this should be unreachable because the command layer maps user commands onto the three supported types.","commonSituations":"Practically never in released Terraform. Can appear when developing a new operation type, when a fork/extension adds an operation without patching the local backend, or when Operation is invoked programmatically with an uninitialized op.Type.","solutions":["File a bug report as the message instructs, including the op.Type value that was passed.","If you are extending Terraform: add a case in the switch (backend.go:306) for the new operation type before it can reach this default.","If calling Operation programmatically, ensure op.Type is set to one of the three valid constants.","On a custom build, verify you are not running a binary where the local backend was patched to remove a case."],"exampleFix":"null","handlingStrategy":"validation","validationCode":"// Reject unsupported op types before calling Operation.\nfunc supportedOp(t backendrun.OperationType) bool {\n    switch t {\n    case backendrun.OperationTypeRefresh, backendrun.OperationTypePlan, backendrun.OperationTypeApply:\n        return true\n    }\n    return false\n}","typeGuard":"null","tryCatchPattern":"// Operation returns (*RunningOperation, error); the unsupported-type case comes back as err.\nrop, err := b.Operation(ctx, op)\nif err != nil {\n    if strings.Contains(err.Error(), \"unsupported operation type\") {\n        panic(\"bug: op.Type = \" + op.Type.String())\n    }\n    return err\n}","preventionTips":["Always initialize op.Type from the command layer's typed constructors; never leave it zero-valued.","When adding a new operation type, update Local.Operation (and any other OperationsBackend) in the same change.","Add a unit test asserting Operation rejects OperationTypeInvalid with the documented message."],"tags":["local-backend","operation","internal-bug","invariant"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}