From 36958cab23981656cde11d5c554adc60175b8a7c Mon Sep 17 00:00:00 2001 From: Dieter Kling <4270462+dkling-it@users.noreply.github.com> Date: Fri, 21 Aug 2026 21:54:34 +0200 Subject: [PATCH] clusters: make `start` a no-op when the cluster isn't TERMINATED `databricks clusters start` returns an INVALID_STATE API error if the target cluster is already RUNNING/PENDING/RESTARTING/RESIZING, even though the command's own help text says "If the cluster is not currently in a TERMINATED state, nothing will happen." Wrap the generated start command's RunE (mirrors the same INVALID_STATE handling already used in bundle/direct/dresources/cluster.go) so that error is swallowed and treated as a successful no-op instead. Fixes #1372 Co-Authored-By: Claude Sonnet 5 --- .../cli/clusters-start-already-running.md | 1 + cmd/workspace/clusters/overrides.go | 24 ++++++++++ cmd/workspace/clusters/overrides_test.go | 45 +++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 .nextchanges/cli/clusters-start-already-running.md create mode 100644 cmd/workspace/clusters/overrides_test.go diff --git a/.nextchanges/cli/clusters-start-already-running.md b/.nextchanges/cli/clusters-start-already-running.md new file mode 100644 index 00000000000..4239d21d40b --- /dev/null +++ b/.nextchanges/cli/clusters-start-already-running.md @@ -0,0 +1 @@ +`databricks clusters start` no longer errors when the cluster is already RUNNING (or PENDING/RESTARTING/RESIZING). It now prints a short message and exits 0, matching the command's own help text ("If the cluster is not currently in a TERMINATED state, nothing will happen"). diff --git a/cmd/workspace/clusters/overrides.go b/cmd/workspace/clusters/overrides.go index 45c530a14a2..fb2b438e7a2 100644 --- a/cmd/workspace/clusters/overrides.go +++ b/cmd/workspace/clusters/overrides.go @@ -1,9 +1,12 @@ package clusters import ( + "errors" + "fmt" "strings" "github.com/databricks/cli/libs/cmdio" + "github.com/databricks/databricks-sdk-go/apierr" "github.com/databricks/databricks-sdk-go/service/compute" "github.com/spf13/cobra" ) @@ -93,8 +96,29 @@ func sparkVersionsOverride(sparkVersionsCmd *cobra.Command) { `) } +// The generated "start" command errors out (INVALID_STATE) if the cluster is +// already RUNNING, PENDING, RESTARTING or RESIZING, even though the command's +// own help text says "If the cluster is not currently in a TERMINATED state, +// nothing will happen." This override makes the command match that +// documented behavior instead of surfacing the API error. +func startOverride(startCmd *cobra.Command, startReq *compute.StartCluster) { + originalRunE := startCmd.RunE + startCmd.RunE = func(cmd *cobra.Command, args []string) error { + err := originalRunE(cmd, args) + + apiErr, ok := errors.AsType[*apierr.APIError](err) + if ok && apiErr.ErrorCode == "INVALID_STATE" { + fmt.Fprintf(cmd.OutOrStdout(), "Cluster %s is not in a TERMINATED state, nothing to do.\n", startReq.ClusterId) + return nil + } + + return err + } +} + func init() { listOverrides = append(listOverrides, listOverride) listNodeTypesOverrides = append(listNodeTypesOverrides, listNodeTypesOverride) sparkVersionsOverrides = append(sparkVersionsOverrides, sparkVersionsOverride) + startOverrides = append(startOverrides, startOverride) } diff --git a/cmd/workspace/clusters/overrides_test.go b/cmd/workspace/clusters/overrides_test.go new file mode 100644 index 00000000000..f717c4c3952 --- /dev/null +++ b/cmd/workspace/clusters/overrides_test.go @@ -0,0 +1,45 @@ +package clusters + +import ( + "bytes" + "errors" + "testing" + + "github.com/databricks/databricks-sdk-go/apierr" + "github.com/databricks/databricks-sdk-go/service/compute" + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestStartOverride_SwallowsInvalidStateError(t *testing.T) { + startReq := &compute.StartCluster{ClusterId: "1234-000000-abcdefg"} + cmd := &cobra.Command{} + cmd.RunE = func(cmd *cobra.Command, args []string) error { + return &apierr.APIError{ErrorCode: "INVALID_STATE", Message: "Cluster is in unexpected state Running."} + } + + startOverride(cmd, startReq) + + var out bytes.Buffer + cmd.SetOut(&out) + err := cmd.RunE(cmd, nil) + + require.NoError(t, err) + assert.Contains(t, out.String(), startReq.ClusterId) +} + +func TestStartOverride_PropagatesOtherErrors(t *testing.T) { + startReq := &compute.StartCluster{ClusterId: "1234-000000-abcdefg"} + cmd := &cobra.Command{} + wantErr := errors.New("boom") + cmd.RunE = func(cmd *cobra.Command, args []string) error { + return wantErr + } + + startOverride(cmd, startReq) + + err := cmd.RunE(cmd, nil) + + assert.Equal(t, wantErr, err) +}