From 5b25ef40a95c7259f26f80bb9275ab6c9342c51c Mon Sep 17 00:00:00 2001 From: Sarah French Date: Thu, 22 Jan 2026 12:15:44 +0000 Subject: [PATCH 1/7] fix: Fail apply command if the plan file was generated for a workspace that isn't the selected workspace. --- internal/command/meta_backend.go | 28 +++++++++++++++ internal/command/meta_backend_errors.go | 21 +++++++++++ internal/command/meta_backend_test.go | 48 +++++++++++++++++++++++++ 3 files changed, 97 insertions(+) diff --git a/internal/command/meta_backend.go b/internal/command/meta_backend.go index 6911fd4c5c97..219d69c133c4 100644 --- a/internal/command/meta_backend.go +++ b/internal/command/meta_backend.go @@ -337,6 +337,34 @@ func (m *Meta) selectWorkspace(b backend.Backend) error { func (m *Meta) BackendForLocalPlan(plan *plans.Plan) (backendrun.OperationsBackend, tfdiags.Diagnostics) { var diags tfdiags.Diagnostics + // Check the workspace name in the plan matches the current workspace + currentWorkspace, err := m.Workspace() + if err != nil { + diags = diags.Append(fmt.Errorf("error determining current workspace when initializing a backend from the plan file: %w", err)) + return nil, diags + } + var plannedWorkspace string + switch { + case plan.StateStore != nil: + plannedWorkspace = plan.StateStore.Workspace + case plan.Backend != nil: + plannedWorkspace = plan.Backend.Workspace + default: + return nil, diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Workspace data missing from plan file", + Detail: fmt.Sprintf("The plan file does not contain a named workspace, so Terraform cannot determine if it was intended to be used with current workspace %q. This is a bug in Terraform and should be reported.", + currentWorkspace, + ), + }) + } + if currentWorkspace != plannedWorkspace { + return nil, diags.Append(&errWrongWorkspaceForPlan{ + currentWorkspace: currentWorkspace, + plannedWorkspace: plannedWorkspace, + }) + } + var b backend.Backend switch { case plan.StateStore != nil: diff --git a/internal/command/meta_backend_errors.go b/internal/command/meta_backend_errors.go index 74314bf752a3..9b98f6783a1e 100644 --- a/internal/command/meta_backend_errors.go +++ b/internal/command/meta_backend_errors.go @@ -9,6 +9,27 @@ import ( "github.com/hashicorp/terraform/internal/tfdiags" ) +// errWrongWorkspaceForPlan is a custom error used to alert users that the plan file they are applying +// describes a workspace that doesn't match the currently selected workspace. +type errWrongWorkspaceForPlan struct { + plannedWorkspace string + currentWorkspace string +} + +func (e *errWrongWorkspaceForPlan) Error() string { + return fmt.Sprintf(`The plan file describes changes to the %q workspace, but the %q workspace is currently selected in the working directory. + +Applying this plan with the incorrect workspace selected could result in state being stored in an unexpected location, or a downstream error +when Terraform attempts apply a plan using the other workspace's state. + +If you'd like to continue to use the plan file, you must run "terraform workspace select %s" to select the correct workspace. +In future make sure the selected workspace is not changed between creating and applying a plan file.`, + e.plannedWorkspace, + e.currentWorkspace, + e.plannedWorkspace, + ) +} + // errBackendLocalRead is a custom error used to alert users that state // files on their local filesystem were not erased successfully after // migrating that state to a remote-state backend. diff --git a/internal/command/meta_backend_test.go b/internal/command/meta_backend_test.go index 1c06899471c9..3386d7b185c5 100644 --- a/internal/command/meta_backend_test.go +++ b/internal/command/meta_backend_test.go @@ -1908,6 +1908,54 @@ func TestMetaBackend_planLocalMatch(t *testing.T) { } } +// A plan that contains a workspace that isn't the currently selected workspace +func TestMetaBackend_planLocal_mismatchedWorkspace(t *testing.T) { + // Create a temporary working directory that is empty + td := t.TempDir() + testCopyDir(t, testFixturePath("backend-plan-local"), td) + t.Chdir(td) + + backendConfigBlock := cty.ObjectVal(map[string]cty.Value{ + "path": cty.NullVal(cty.String), + "workspace_dir": cty.NullVal(cty.String), + }) + backendConfigRaw, err := plans.NewDynamicValue(backendConfigBlock, backendConfigBlock.Type()) + if err != nil { + t.Fatal(err) + } + defaultWorkspace := "default" + plan := &plans.Plan{ + Backend: &plans.Backend{ + Type: "local", + Config: backendConfigRaw, + Workspace: defaultWorkspace, + }, + } + + // Setup the meta + m := testMetaBackend(t, nil) + selectedWorkspace := "foobar" + err = m.SetWorkspace(selectedWorkspace) + if err != nil { + t.Fatalf("error in test setup: %s", err) + } + + // Get the backend + _, diags := m.BackendForLocalPlan(plan) + if !diags.HasErrors() { + t.Fatalf("expected an error but got none: %s", diags.ErrWithWarnings()) + } + expectedMsg := fmt.Sprintf("The plan file describes changes to the %q workspace, but the %q workspace is currently selected in the working directory", + defaultWorkspace, + selectedWorkspace, + ) + if !strings.Contains(diags.Err().Error(), expectedMsg) { + t.Fatalf("expected error to include %q, but got:\n%s", + expectedMsg, + diags.Err()) + } +} + // init a backend using -backend-config options multiple times func TestMetaBackend_configureBackendWithExtra(t *testing.T) { // Create a temporary working directory that is empty From ff2d5005ffd1109f0913801aa06551357fab485c Mon Sep 17 00:00:00 2001 From: Sarah French Date: Mon, 1 Dec 2025 11:49:59 +0000 Subject: [PATCH 2/7] Add change file --- .changes/v1.15/BUG FIXES-20251201-114950.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changes/v1.15/BUG FIXES-20251201-114950.yaml diff --git a/.changes/v1.15/BUG FIXES-20251201-114950.yaml b/.changes/v1.15/BUG FIXES-20251201-114950.yaml new file mode 100644 index 000000000000..cfa8ded58b62 --- /dev/null +++ b/.changes/v1.15/BUG FIXES-20251201-114950.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: 'apply: Terraform will raise an explicit error if a plan file intended for one workspace is applied against another workspace' +time: 2025-12-01T11:49:50.360928Z +custom: + Issue: "37954" From 0cee065cf1706c5f4fead92e413c628126422959 Mon Sep 17 00:00:00 2001 From: Sarah French Date: Mon, 1 Dec 2025 13:39:53 +0000 Subject: [PATCH 3/7] test: Update test helper to include Workspace name in plan representation --- internal/command/command_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/command/command_test.go b/internal/command/command_test.go index 2c0486dca33c..7c0609388b45 100644 --- a/internal/command/command_test.go +++ b/internal/command/command_test.go @@ -192,8 +192,9 @@ func testPlan(t *testing.T) *plans.Plan { // This is just a placeholder so that the plan file can be written // out. Caller may wish to override it to something more "real" // where the plan will actually be subsequently applied. - Type: "local", - Config: backendConfigRaw, + Type: "local", + Config: backendConfigRaw, + Workspace: "default", }, Changes: plans.NewChangesSrc(), From 72e9760e5034c45f976d7fc434dbdc12d5ef9af3 Mon Sep 17 00:00:00 2001 From: Sarah French Date: Mon, 1 Dec 2025 13:40:21 +0000 Subject: [PATCH 4/7] fix: Make error message more generic, so is applicable to backend and cloud blocks. --- internal/command/meta_backend_errors.go | 2 +- internal/command/meta_backend_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/command/meta_backend_errors.go b/internal/command/meta_backend_errors.go index 9b98f6783a1e..e0f312f5a508 100644 --- a/internal/command/meta_backend_errors.go +++ b/internal/command/meta_backend_errors.go @@ -17,7 +17,7 @@ type errWrongWorkspaceForPlan struct { } func (e *errWrongWorkspaceForPlan) Error() string { - return fmt.Sprintf(`The plan file describes changes to the %q workspace, but the %q workspace is currently selected in the working directory. + return fmt.Sprintf(`The plan file describes changes to the %q workspace, but the %q workspace is currently in use. Applying this plan with the incorrect workspace selected could result in state being stored in an unexpected location, or a downstream error when Terraform attempts apply a plan using the other workspace's state. diff --git a/internal/command/meta_backend_test.go b/internal/command/meta_backend_test.go index 3386d7b185c5..1b007bb116c5 100644 --- a/internal/command/meta_backend_test.go +++ b/internal/command/meta_backend_test.go @@ -1945,7 +1945,7 @@ func TestMetaBackend_planLocal_mismatchedWorkspace(t *testing.T) { if !diags.HasErrors() { t.Fatalf("expected an error but got none: %s", diags.ErrWithWarnings()) } - expectedMsg := fmt.Sprintf("The plan file describes changes to the %q workspace, but the %q workspace is currently selected in the working directory", + expectedMsg := fmt.Sprintf("The plan file describes changes to the %q workspace, but the %q workspace is currently in use", defaultWorkspace, selectedWorkspace, ) From 1dd8658aeef1c6c9ff9f96a01f11ad54b85b8a1a Mon Sep 17 00:00:00 2001 From: Sarah French Date: Mon, 1 Dec 2025 15:51:16 +0000 Subject: [PATCH 5/7] fix: Make error message specific to backend or cloud block --- internal/command/meta_backend.go | 4 ++++ internal/command/meta_backend_errors.go | 29 ++++++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/internal/command/meta_backend.go b/internal/command/meta_backend.go index 219d69c133c4..7a3342ebb784 100644 --- a/internal/command/meta_backend.go +++ b/internal/command/meta_backend.go @@ -344,11 +344,14 @@ func (m *Meta) BackendForLocalPlan(plan *plans.Plan) (backendrun.OperationsBacke return nil, diags } var plannedWorkspace string + var isCloud bool switch { case plan.StateStore != nil: plannedWorkspace = plan.StateStore.Workspace + isCloud = false case plan.Backend != nil: plannedWorkspace = plan.Backend.Workspace + isCloud = plan.Backend.Type == "cloud" default: return nil, diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagError, @@ -362,6 +365,7 @@ func (m *Meta) BackendForLocalPlan(plan *plans.Plan) (backendrun.OperationsBacke return nil, diags.Append(&errWrongWorkspaceForPlan{ currentWorkspace: currentWorkspace, plannedWorkspace: plannedWorkspace, + isCloud: isCloud, }) } diff --git a/internal/command/meta_backend_errors.go b/internal/command/meta_backend_errors.go index e0f312f5a508..02d966a3070e 100644 --- a/internal/command/meta_backend_errors.go +++ b/internal/command/meta_backend_errors.go @@ -11,23 +11,40 @@ import ( // errWrongWorkspaceForPlan is a custom error used to alert users that the plan file they are applying // describes a workspace that doesn't match the currently selected workspace. +// +// This needs to render slightly different errors depending on whether we're using: +// > CE Workspaces (remote-state backends, local backends) +// > HCP Terraform Workspaces (cloud backend) type errWrongWorkspaceForPlan struct { plannedWorkspace string currentWorkspace string + isCloud bool } func (e *errWrongWorkspaceForPlan) Error() string { - return fmt.Sprintf(`The plan file describes changes to the %q workspace, but the %q workspace is currently in use. + msg := fmt.Sprintf(`The plan file describes changes to the %q workspace, but the %q workspace is currently in use. Applying this plan with the incorrect workspace selected could result in state being stored in an unexpected location, or a downstream error -when Terraform attempts apply a plan using the other workspace's state. - -If you'd like to continue to use the plan file, you must run "terraform workspace select %s" to select the correct workspace. -In future make sure the selected workspace is not changed between creating and applying a plan file.`, +when Terraform attempts apply a plan using the other workspace's state.`, e.plannedWorkspace, e.currentWorkspace, - e.plannedWorkspace, ) + + // For users to understand what's happened and how to correct it we'll give some guidance, + // but that guidance depends on whether a cloud backend is in use or not. + if e.isCloud { + // When using the cloud backend the solution is to focus on the cloud block and running init + msg = msg + fmt.Sprintf(` If you\'d like to continue to use the plan file, make sure the cloud block in your configuration contains the workspace name %q. +In future, make sure your cloud block is correct and unchanged since the last time you performed "terraform init" before creating a plan.`, e.plannedWorkspace) + } else { + // When using the backend block the solution is to not select a different workspace + // between plan and apply operations. + msg = msg + fmt.Sprintf(` If you\'d like to continue to use the plan file, you must run "terraform workspace select %s" to select the matching workspace. +In future make sure the selected workspace is not changed between creating and applying a plan file. +`, e.plannedWorkspace) + } + + return msg } // errBackendLocalRead is a custom error used to alert users that state From c2244f7507040c5e9db4ed91aeda122e6d8398b1 Mon Sep 17 00:00:00 2001 From: Sarah French Date: Mon, 1 Dec 2025 15:52:08 +0000 Subject: [PATCH 6/7] test: Add separate tests for backend/cloud usage --- internal/command/meta_backend_test.go | 142 ++++++++++++++++++-------- 1 file changed, 98 insertions(+), 44 deletions(-) diff --git a/internal/command/meta_backend_test.go b/internal/command/meta_backend_test.go index 1b007bb116c5..b4beee76f274 100644 --- a/internal/command/meta_backend_test.go +++ b/internal/command/meta_backend_test.go @@ -1910,50 +1910,107 @@ func TestMetaBackend_planLocalMatch(t *testing.T) { // A plan that contains a workspace that isn't the currently selected workspace func TestMetaBackend_planLocal_mismatchedWorkspace(t *testing.T) { - // Create a temporary working directory that is empty - td := t.TempDir() - testCopyDir(t, testFixturePath("backend-plan-local"), td) - t.Chdir(td) + t.Run("local backend", func(t *testing.T) { + td := t.TempDir() + t.Chdir(td) - backendConfigBlock := cty.ObjectVal(map[string]cty.Value{ - "path": cty.NullVal(cty.String), - "workspace_dir": cty.NullVal(cty.String), + backendConfigBlock := cty.ObjectVal(map[string]cty.Value{ + "path": cty.NullVal(cty.String), + "workspace_dir": cty.NullVal(cty.String), + }) + backendConfigRaw, err := plans.NewDynamicValue(backendConfigBlock, backendConfigBlock.Type()) + if err != nil { + t.Fatal(err) + } + planWorkspace := "default" + plan := &plans.Plan{ + Backend: &plans.Backend{ + Type: "local", + Config: backendConfigRaw, + Workspace: planWorkspace, + }, + } + + // Setup the meta + m := testMetaBackend(t, nil) + otherWorkspace := "foobar" + err = m.SetWorkspace(otherWorkspace) + if err != nil { + t.Fatalf("error in test setup: %s", err) + } + + // Get the backend + _, diags := m.BackendForLocalPlan(plan) + if !diags.HasErrors() { + t.Fatalf("expected an error but got none: %s", diags.ErrWithWarnings()) + } + expectedMsgs := []string{ + fmt.Sprintf("The plan file describes changes to the %q workspace, but the %q workspace is currently in use", + planWorkspace, + otherWorkspace, + ), + fmt.Sprintf("terraform workspace select %s", planWorkspace), + } + for _, msg := range expectedMsgs { + if !strings.Contains(diags.Err().Error(), msg) { + t.Fatalf("expected error to include %q, but got:\n%s", + msg, + diags.Err()) + } + } }) - backendConfigRaw, err := plans.NewDynamicValue(backendConfigBlock, backendConfigBlock.Type()) - if err != nil { - t.Fatal(err) - } - defaultWorkspace := "default" - plan := &plans.Plan{ - Backend: &plans.Backend{ - Type: "local", - Config: backendConfigRaw, - Workspace: defaultWorkspace, - }, - } - // Setup the meta - m := testMetaBackend(t, nil) - selectedWorkspace := "foobar" - err = m.SetWorkspace(selectedWorkspace) - if err != nil { - t.Fatalf("error in test setup: %s", err) - } + t.Run("cloud backend", func(t *testing.T) { + td := t.TempDir() + t.Chdir(td) - // Get the backend - _, diags := m.BackendForLocalPlan(plan) - if !diags.HasErrors() { - t.Fatalf("expected an error but got none: %s", diags.ErrWithWarnings()) - } - expectedMsg := fmt.Sprintf("The plan file describes changes to the %q workspace, but the %q workspace is currently in use", - defaultWorkspace, - selectedWorkspace, - ) - if !strings.Contains(diags.Err().Error(), expectedMsg) { - t.Fatalf("expected error to include %q, but got:\n%s", - expectedMsg, - diags.Err()) - } + planWorkspace := "prod" + cloudConfigBlock := cty.ObjectVal(map[string]cty.Value{ + "organization": cty.StringVal("hashicorp"), + "workspaces": cty.ObjectVal(map[string]cty.Value{ + "name": cty.StringVal(planWorkspace), + }), + }) + cloudConfigRaw, err := plans.NewDynamicValue(cloudConfigBlock, cloudConfigBlock.Type()) + if err != nil { + t.Fatal(err) + } + plan := &plans.Plan{ + Backend: &plans.Backend{ + Type: "cloud", + Config: cloudConfigRaw, + Workspace: planWorkspace, + }, + } + + // Setup the meta + m := testMetaBackend(t, nil) + otherWorkspace := "foobar" + err = m.SetWorkspace(otherWorkspace) + if err != nil { + t.Fatalf("error in test setup: %s", err) + } + + // Get the backend + _, diags := m.BackendForLocalPlan(plan) + if !diags.HasErrors() { + t.Fatalf("expected an error but got none: %s", diags.ErrWithWarnings()) + } + expectedMsgs := []string{ + fmt.Sprintf("The plan file describes changes to the %q workspace, but the %q workspace is currently in use", + planWorkspace, + otherWorkspace, + ), + fmt.Sprintf(`If you\'d like to continue to use the plan file, make sure the cloud block in your configuration contains the workspace name %q`, planWorkspace), + } + for _, msg := range expectedMsgs { + if !strings.Contains(diags.Err().Error(), msg) { + t.Fatalf("expected error to include `%s`, but got:\n%s", + msg, + diags.Err()) + } + } + }) } // init a backend using -backend-config options multiple times @@ -2108,7 +2165,6 @@ func TestBackendFromState(t *testing.T) { } func Test_determineInitReason(t *testing.T) { - cases := map[string]struct { cloudMode cloud.ConfigChangeMode backendState workdir.BackendStateFile @@ -2318,7 +2374,6 @@ func TestMetaBackend_configureStateStoreVariableUse(t *testing.T) { if !strings.Contains(err.Err().Error(), tc.wantErr) { t.Fatalf("error should include %q, got: %s", tc.wantErr, err.Err()) } - }) } } @@ -2800,7 +2855,7 @@ func TestMetaBackend_stateStoreConfig(t *testing.T) { t.Run("error - no config present", func(t *testing.T) { opts := &BackendOpts{ - StateStoreConfig: nil, //unset + StateStoreConfig: nil, // unset Init: true, Locks: locks, } @@ -2986,7 +3041,6 @@ func Test_getStateStorageProviderVersion(t *testing.T) { } func TestMetaBackend_prepareBackend(t *testing.T) { - t.Run("it returns a cloud backend from cloud backend config", func(t *testing.T) { // Create a temporary working directory with cloud configuration in td := t.TempDir() From 4aba1684f39f363716914ea6c45c435fea9a199a Mon Sep 17 00:00:00 2001 From: Sarah French Date: Mon, 1 Dec 2025 16:00:00 +0000 Subject: [PATCH 7/7] test: Update remaining tests to include a value for Workspace in mocked plans --- internal/backend/local/backend_local_test.go | 5 ++- internal/backend/local/backend_plan_test.go | 40 ++++++++++++-------- internal/command/apply_test.go | 5 ++- internal/command/graph_test.go | 5 ++- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/internal/backend/local/backend_local_test.go b/internal/backend/local/backend_local_test.go index 2e84d01f6a64..83c0c17cbd9b 100644 --- a/internal/backend/local/backend_local_test.go +++ b/internal/backend/local/backend_local_test.go @@ -161,8 +161,9 @@ func TestLocalRun_stalePlan(t *testing.T) { UIMode: plans.NormalMode, Changes: plans.NewChangesSrc(), Backend: &plans.Backend{ - Type: "local", - Config: backendConfigRaw, + Type: "local", + Config: backendConfigRaw, + Workspace: "default", }, PrevRunState: states.NewState(), PriorState: states.NewState(), diff --git a/internal/backend/local/backend_plan_test.go b/internal/backend/local/backend_plan_test.go index 1f6a10f25024..f7ecb0f6f4bd 100644 --- a/internal/backend/local/backend_plan_test.go +++ b/internal/backend/local/backend_plan_test.go @@ -207,8 +207,9 @@ func TestLocal_planOutputsChanged(t *testing.T) { } op.PlanOutBackend = &plans.Backend{ // Just a placeholder so that we can generate a valid plan file. - Type: "local", - Config: cfgRaw, + Type: "local", + Config: cfgRaw, + Workspace: "default", } run, err := b.Operation(context.Background(), op) if err != nil { @@ -263,8 +264,9 @@ func TestLocal_planModuleOutputsChanged(t *testing.T) { t.Fatal(err) } op.PlanOutBackend = &plans.Backend{ - Type: "local", - Config: cfgRaw, + Type: "local", + Config: cfgRaw, + Workspace: "default", } run, err := b.Operation(context.Background(), op) if err != nil { @@ -305,8 +307,9 @@ func TestLocal_planTainted(t *testing.T) { } op.PlanOutBackend = &plans.Backend{ // Just a placeholder so that we can generate a valid plan file. - Type: "local", - Config: cfgRaw, + Type: "local", + Config: cfgRaw, + Workspace: "default", } run, err := b.Operation(context.Background(), op) if err != nil { @@ -384,8 +387,9 @@ func TestLocal_planDeposedOnly(t *testing.T) { } op.PlanOutBackend = &plans.Backend{ // Just a placeholder so that we can generate a valid plan file. - Type: "local", - Config: cfgRaw, + Type: "local", + Config: cfgRaw, + Workspace: "default", } run, err := b.Operation(context.Background(), op) if err != nil { @@ -475,8 +479,9 @@ func TestLocal_planTainted_createBeforeDestroy(t *testing.T) { } op.PlanOutBackend = &plans.Backend{ // Just a placeholder so that we can generate a valid plan file. - Type: "local", - Config: cfgRaw, + Type: "local", + Config: cfgRaw, + Workspace: "default", } run, err := b.Operation(context.Background(), op) if err != nil { @@ -566,8 +571,9 @@ func TestLocal_planDestroy(t *testing.T) { } op.PlanOutBackend = &plans.Backend{ // Just a placeholder so that we can generate a valid plan file. - Type: "local", - Config: cfgRaw, + Type: "local", + Config: cfgRaw, + Workspace: "default", } run, err := b.Operation(context.Background(), op) @@ -618,8 +624,9 @@ func TestLocal_planDestroy_withDataSources(t *testing.T) { } op.PlanOutBackend = &plans.Backend{ // Just a placeholder so that we can generate a valid plan file. - Type: "local", - Config: cfgRaw, + Type: "local", + Config: cfgRaw, + Workspace: "default", } run, err := b.Operation(context.Background(), op) @@ -690,8 +697,9 @@ func TestLocal_planOutPathNoChange(t *testing.T) { } op.PlanOutBackend = &plans.Backend{ // Just a placeholder so that we can generate a valid plan file. - Type: "local", - Config: cfgRaw, + Type: "local", + Config: cfgRaw, + Workspace: "default", } op.PlanRefresh = true diff --git a/internal/command/apply_test.go b/internal/command/apply_test.go index 2e7e22a8500d..b3c91dbef438 100644 --- a/internal/command/apply_test.go +++ b/internal/command/apply_test.go @@ -1087,8 +1087,9 @@ func TestApply_plan_remoteState(t *testing.T) { } planPath := testPlanFile(t, snap, state, &plans.Plan{ Backend: &plans.Backend{ - Type: "http", - Config: backendConfigRaw, + Type: "http", + Config: backendConfigRaw, + Workspace: "default", }, Changes: plans.NewChangesSrc(), }) diff --git a/internal/command/graph_test.go b/internal/command/graph_test.go index dc98f74c71f7..8193614329de 100644 --- a/internal/command/graph_test.go +++ b/internal/command/graph_test.go @@ -329,8 +329,9 @@ func TestGraph_applyPhaseSavedPlan(t *testing.T) { // Doesn't actually matter since we aren't going to activate the backend // for this command anyway, but we need something here for the plan // file writer to succeed. - Type: "placeholder", - Config: emptyObj, + Type: "placeholder", + Config: emptyObj, + Workspace: "default", } _, configSnap := testModuleWithSnapshot(t, "graph")