Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions NEXT_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

## Release v0.300.0

### Notable Changes

### CLI

* Added `databricks aitools` command group for installing Databricks skills into your coding agents (Claude Code, Cursor, Codex CLI, OpenCode, GitHub Copilot, Antigravity). Skills are fetched from [github.com/databricks/databricks-agent-skills](https://github.com/databricks/databricks-agent-skills) and either symlinked into each agent's skills directory or copied into the current project. Use `databricks aitools install` to set up, `update` to pull newer versions, `list` to see what's available, and `uninstall` to remove them.
* `databricks api` now works against unified hosts. Adds `--account` to scope a call to the account API and `--workspace-id` to override the workspace routing identifier per call. A `?o=<workspace-id>` query parameter on the path (the SPOG URL convention used by the Databricks UI) is also recognized as a per-call workspace override, so URLs pasted from the browser route correctly.

* Improve `auth token` error formatting for easier copy-paste of login commands ([#4602](https://github.com/databricks/cli/pull/4602))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This link still points to the replaced PR (#4602). Since this PR is the one that will merge, the release note should reference #5115; otherwise the shipped changelog sends readers to the abandoned PR.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this links the superseded #4602, but this branch will merge as #5115. Worth pointing release-note readers at the actual merged PR.


### Bundles
* Make sure warnings asking for approval are understood by agents ([#5239](https://github.com/databricks/cli/pull/5239))

### Dependency updates
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,10 @@ logfood (Default) [DATABRICKS_URL] NO

=== Logged out profile should no longer return a token
>>> musterr [CLI] auth token --profile logfood
Error: cache: databricks OAuth is not configured for this host. Try logging in again with `databricks auth login --profile logfood` before retrying. If this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new
Error: cache: databricks OAuth is not configured for this host.

To reauthenticate, run the following command:

$ databricks auth login --profile logfood --workspace-id [NUMID]

If this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
Error: A new access token could not be retrieved because the refresh token is invalid. To reauthenticate, run the following command:
$ databricks auth login --profile test-profile
Error: A new access token could not be retrieved because the refresh token is invalid.

To reauthenticate, run the following command:

$ databricks auth login --profile test-profile --workspace-id [NUMID]

Exit code: 1
8 changes: 7 additions & 1 deletion acceptance/cmd/auth/token/force-refresh-no-cache/output.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
Error: cache: databricks OAuth is not configured for this host. Try logging in again with `databricks auth login --profile test-profile` before retrying. If this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new
Error: cache: databricks OAuth is not configured for this host.

To reauthenticate, run the following command:

$ databricks auth login --profile test-profile --workspace-id [NUMID]

If this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new

Exit code: 1
8 changes: 7 additions & 1 deletion acceptance/cmd/auth/token/output.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@

>>> [CLI] auth token --host [DATABRICKS_URL]
Error: cache: databricks OAuth is not configured for this host. Try logging in again with `databricks auth login --host [DATABRICKS_URL]` before retrying. If this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new
Error: cache: databricks OAuth is not configured for this host.

To reauthenticate, run the following command:

$ databricks auth login --host [DATABRICKS_URL]

If this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new

Exit code: 1
16 changes: 8 additions & 8 deletions cmd/auth/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import (
"golang.org/x/oauth2"
)

func helpfulError(ctx context.Context, profile string, persistentAuth u2m.OAuthArgument) string {
loginMsg := auth.BuildLoginCommand(ctx, profile, persistentAuth)
return fmt.Sprintf("Try logging in again with `%s` before retrying. If this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new", loginMsg)
func helpfulError(ctx context.Context, profile, workspaceID string, persistentAuth u2m.OAuthArgument) string {
loginMsg := auth.BuildLoginCommand(ctx, profile, workspaceID, persistentAuth)
return fmt.Sprintf("To reauthenticate, run the following command:\n\n $ %s\n\nIf this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new", loginMsg)
}

func newTokenCommand(authArguments *auth.AuthArguments) *cobra.Command {
Expand Down Expand Up @@ -267,8 +267,8 @@ func loadToken(ctx context.Context, args loadTokenArgs) (*oauth2.Token, error) {
allArgs = append(allArgs, u2m.WithOAuthArgument(oauthArgument))
persistentAuth, err := u2m.NewPersistentAuth(ctx, allArgs...)
if err != nil {
helpMsg := helpfulError(ctx, args.profileName, oauthArgument)
return nil, fmt.Errorf("%w. %s", err, helpMsg)
helpMsg := helpfulError(ctx, args.profileName, args.authArguments.WorkspaceID, oauthArgument)
Comment on lines 267 to +270
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: why include --workspace-id on the profile path?

When the user invokes databricks auth token --profile foo and we suggest databricks auth login --profile foo --workspace-id <id>, the --workspace-id is technically redundant — auth login --profile foo will already pick up the workspace_id stored in the profile.

Including it is meaningful only if (a) the profile's persisted workspace_id has drifted from the failing call's workspace_id, or (b) the user typed --workspace-id on the failing call and we want to preserve that intent. Both are plausible, but the doc-comment on BuildLoginCommand only motivates the unified-host case.

Not asking for a code change — just want to confirm this was deliberate. If yes, a one-line addendum to the doc-comment (e.g. "…also re-emitted on the profile path so the suggested reauth pins the same workspace_id the failing call resolved against") would close the loop.

return nil, fmt.Errorf("%w.\n\n%s", err, helpMsg)
}
var t *oauth2.Token
if args.forceRefresh {
Expand All @@ -289,11 +289,11 @@ func loadToken(ctx context.Context, args loadTokenArgs) (*oauth2.Token, error) {
// This is captured in an acceptance test under "cmd/auth/token".
err = errors.New("cache: databricks OAuth is not configured for this host")
}
if rewritten, rewrittenErr := auth.RewriteAuthError(ctx, args.authArguments.Host, args.authArguments.AccountID, args.profileName, err); rewritten {
if rewritten, rewrittenErr := auth.RewriteAuthError(ctx, args.authArguments.Host, args.authArguments.AccountID, args.authArguments.WorkspaceID, args.profileName, err); rewritten {
return nil, rewrittenErr
}
helpMsg := helpfulError(ctx, args.profileName, oauthArgument)
return nil, fmt.Errorf("%w. %s", err, helpMsg)
helpMsg := helpfulError(ctx, args.profileName, args.authArguments.WorkspaceID, oauthArgument)
return nil, fmt.Errorf("%w.\n\n%s", err, helpMsg)
}
return t, nil
}
Expand Down
32 changes: 20 additions & 12 deletions cmd/auth/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,9 @@ func TestToken_loadToken(t *testing.T) {
u2m.WithHttpClient(&http.Client{Transport: fixtures.SliceTransport{refreshFailureTokenResponse}}),
},
},
wantErr: `A new access token could not be retrieved because the refresh token is invalid. To reauthenticate, run the following command:
$ databricks auth login --profile expired`,
wantErr: "A new access token could not be retrieved because the refresh token is invalid.\n\n" +
"To reauthenticate, run the following command:\n\n" +
" $ databricks auth login --profile expired",
},
{
name: "prints helpful login message on refresh failure when host is specified",
Expand All @@ -249,8 +250,9 @@ func TestToken_loadToken(t *testing.T) {
u2m.WithHttpClient(&http.Client{Transport: fixtures.SliceTransport{refreshFailureTokenResponse}}),
},
},
wantErr: `A new access token could not be retrieved because the refresh token is invalid. To reauthenticate, run the following command:
$ databricks auth login --profile expired`,
wantErr: "A new access token could not be retrieved because the refresh token is invalid.\n\n" +
"To reauthenticate, run the following command:\n\n" +
" $ databricks auth login --profile expired",
},
{
name: "prints helpful login message on invalid response",
Expand All @@ -267,8 +269,10 @@ func TestToken_loadToken(t *testing.T) {
u2m.WithHttpClient(&http.Client{Transport: fixtures.SliceTransport{refreshFailureInvalidResponse}}),
},
},
wantErr: "token refresh: oauth2: cannot parse json: invalid character 'N' looking for beginning of value. Try logging in again with " +
"`databricks auth login --profile active` before retrying. If this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new",
wantErr: "token refresh: oauth2: cannot parse json: invalid character 'N' looking for beginning of value.\n\n" +
"To reauthenticate, run the following command:\n\n" +
" $ databricks auth login --profile active\n\n" +
"If this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new",
},
{
name: "prints helpful login message on other error response",
Expand All @@ -285,8 +289,10 @@ func TestToken_loadToken(t *testing.T) {
u2m.WithHttpClient(&http.Client{Transport: fixtures.SliceTransport{refreshFailureOtherError}}),
},
},
wantErr: "token refresh: Databricks is down (error code: other_error). Try logging in again with " +
"`databricks auth login --profile active` before retrying. If this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new",
wantErr: "token refresh: Databricks is down (error code: other_error).\n\n" +
"To reauthenticate, run the following command:\n\n" +
" $ databricks auth login --profile active\n\n" +
"If this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new",
},
{
name: "succeeds with profile",
Expand Down Expand Up @@ -404,8 +410,9 @@ func TestToken_loadToken(t *testing.T) {
u2m.WithOAuthEndpointSupplier(&MockApiClient{}),
},
},
wantErr: "cache: databricks OAuth is not configured for this host. " +
"Try logging in again with `databricks auth login --host https://nonexistent.cloud.databricks.com` before retrying. " +
wantErr: "cache: databricks OAuth is not configured for this host.\n\n" +
"To reauthenticate, run the following command:\n\n" +
" $ databricks auth login --host https://nonexistent.cloud.databricks.com\n\n" +
"If this fails, please report this issue to the Databricks CLI maintainers at https://github.com/databricks/cli/issues/new",
},
{
Expand Down Expand Up @@ -803,8 +810,9 @@ func TestToken_loadToken(t *testing.T) {
u2m.WithHttpClient(&http.Client{Transport: fixtures.SliceTransport{refreshFailureTokenResponse}}),
},
},
wantErr: `A new access token could not be retrieved because the refresh token is invalid. To reauthenticate, run the following command:
$ databricks auth login --profile valid-token`,
wantErr: "A new access token could not be retrieved because the refresh token is invalid.\n\n" +
"To reauthenticate, run the following command:\n\n" +
" $ databricks auth login --profile valid-token",
},
}
for _, c := range cases {
Expand Down
2 changes: 1 addition & 1 deletion cmd/root/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ func emptyHttpRequest(ctx context.Context) *http.Request {
}

func renderError(ctx context.Context, cfg *config.Config, err error) error {
if rewritten, newErr := auth.RewriteAuthError(ctx, cfg.Host, cfg.AccountID, cfg.Profile, err); rewritten {
if rewritten, newErr := auth.RewriteAuthError(ctx, cfg.Host, cfg.AccountID, cfg.WorkspaceID, cfg.Profile, err); rewritten {
return newErr
}
return err
Expand Down
61 changes: 49 additions & 12 deletions libs/auth/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"net/http"
"strings"

"github.com/databricks/cli/libs/shellquote"
"github.com/databricks/databricks-sdk-go/apierr"
"github.com/databricks/databricks-sdk-go/config"
"github.com/databricks/databricks-sdk-go/credentials/u2m"
Expand Down Expand Up @@ -53,18 +54,20 @@ func AuthTypeDisplayName(authType string) string {

// RewriteAuthError rewrites the error message for invalid refresh token error.
// It returns whether the error was rewritten and the rewritten error.
func RewriteAuthError(ctx context.Context, host, accountId, profile string, err error) (bool, error) {
func RewriteAuthError(ctx context.Context, host, accountId, workspaceId, profile string, err error) (bool, error) {
target := &u2m.InvalidRefreshTokenError{}
if errors.As(err, &target) {
oauthArgument, err := AuthArguments{
Host: host,
AccountID: accountId,
Host: host,
AccountID: accountId,
WorkspaceID: workspaceId,
}.ToOAuthArgument()
if err != nil {
return false, err
}
msg := `A new access token could not be retrieved because the refresh token is invalid. To reauthenticate, run the following command:
$ ` + BuildLoginCommand(ctx, profile, oauthArgument)
msg := "A new access token could not be retrieved because the refresh token is invalid.\n\n" +
"To reauthenticate, run the following command:\n\n" +
" $ " + BuildLoginCommand(ctx, profile, workspaceId, oauthArgument)
return true, errors.New(msg)
}
return false, err
Expand Down Expand Up @@ -118,9 +121,11 @@ func writeReauthSteps(ctx context.Context, cfg *config.Config, b *strings.Builde
switch strings.ToLower(cfg.AuthType) {
case AuthTypeDatabricksCli:
// When profile is set, BuildLoginCommand uses --profile and ignores
// the OAuthArgument, so skip the conversion entirely.
// the OAuthArgument, so skip the conversion entirely. Route through
// the helper so this branch picks up shell-quoting on the profile name
// and emits --workspace-id consistently with the host-based branch.
if cfg.Profile != "" {
fmt.Fprintf(b, "\n - Re-authenticate: databricks auth login --profile %s", cfg.Profile)
fmt.Fprintf(b, "\n - Re-authenticate: %s", BuildLoginCommand(ctx, cfg.Profile, cfg.WorkspaceID, nil))
return
}
oauthArg, argErr := AuthArguments{
Expand All @@ -133,7 +138,7 @@ func writeReauthSteps(ctx context.Context, cfg *config.Config, b *strings.Builde
fmt.Fprint(b, "\n - Re-authenticate: databricks auth login")
return
}
fmt.Fprintf(b, "\n - Re-authenticate: %s", BuildLoginCommand(ctx, "", oauthArg))
fmt.Fprintf(b, "\n - Re-authenticate: %s", BuildLoginCommand(ctx, "", cfg.WorkspaceID, oauthArg))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This non-profile branch now gets the safer command construction, but the cfg.Profile != "" branch just above still formats databricks auth login --profile %s by hand. That means profile names with spaces or shell metacharacters still produce broken/unsafe copy-paste commands in EnrichAuthError. Can the profile branch use BuildLoginCommand(ctx, cfg.Profile, cfg.WorkspaceID, nil) too, or otherwise quote consistently?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important: the sibling profile branch (line 125) wasn't updated.

This branch correctly routes through BuildLoginCommand(ctx, "", cfg.WorkspaceID, oauthArg) now. But the if cfg.Profile != "" branch above (line 125 in the new file) still does fmt.Fprintf(b, "... --profile %s", cfg.Profile), bypassing the helper.

Result: a 401 on a profile-based databricks-cli call (the most common case) renders without --workspace-id and without shell-quoting, while this branch and the new helpfulError path do both. That makes the PR's own consistency claim only half-true — and on unified/SPOG hosts the suggested command can target the wrong workspace.

Fix: route the profile branch through BuildLoginCommand(ctx, cfg.Profile, cfg.WorkspaceID, nil). Add a test using a profile with WorkspaceID set, and ideally a profile name needing shell-quoting (e.g. with a space) to cover both improvements at once.


case AuthTypePat:
if cfg.Profile != "" {
Expand All @@ -160,28 +165,60 @@ func writeReauthSteps(ctx context.Context, cfg *config.Config, b *strings.Builde
}
}

// BuildLoginCommand builds the login command for the given OAuth argument or profile.
func BuildLoginCommand(ctx context.Context, profile string, arg u2m.OAuthArgument) string {
// BuildLoginCommand builds the login command for the given OAuth argument or
// profile. Each argument is shell-quoted so the rendered command is safe to
// copy-paste even when host, profile, or account-id values contain spaces or
// shell metacharacters.
//
// workspaceID, when non-empty and not the WorkspaceIDNone sentinel, is
// emitted as --workspace-id for unified hosts so the suggested reauth
// targets the same workspace the failing call resolved against (the
// information the OAuthArgument otherwise drops). It is also re-emitted on
// the profile path so the suggested reauth pins the same workspace_id the
// failing call resolved against, even if the profile's persisted value has
// drifted.
//
// For AccountOAuthArgument and WorkspaceOAuthArgument, workspaceID is
// intentionally ignored: account args target the account API, and workspace
// args already identify a workspace via --host.
func BuildLoginCommand(ctx context.Context, profile, workspaceID string, arg u2m.OAuthArgument) string {
cmd := []string{
"databricks",
"auth",
"login",
}
if profile != "" {
cmd = append(cmd, "--profile", profile)
if isExplicitWorkspaceID(workspaceID) {
cmd = append(cmd, "--workspace-id", workspaceID)
}
} else {
switch arg := arg.(type) {
case u2m.UnifiedOAuthArgument:
// Discovery handles unified-host routing from --host + --account-id,
// so we no longer suggest --experimental-is-unified-host here.
cmd = append(cmd, "--host", arg.GetHost(), "--account-id", arg.GetAccountId())
if isExplicitWorkspaceID(workspaceID) {
cmd = append(cmd, "--workspace-id", workspaceID)
}
case u2m.AccountOAuthArgument:
cmd = append(cmd, "--host", arg.GetAccountHost(), "--account-id", arg.GetAccountId())
case u2m.WorkspaceOAuthArgument:
cmd = append(cmd, "--host", arg.GetWorkspaceHost())
}
}
return strings.Join(cmd, " ")
quoted := make([]string, len(cmd))
for i, c := range cmd {
quoted[i] = shellquote.BashArg(c)
}
return strings.Join(quoted, " ")
}

// isExplicitWorkspaceID reports whether workspaceID names a real workspace
// (not the "none" sentinel persisted to .databrickscfg when the user
// explicitly skipped workspace selection).
func isExplicitWorkspaceID(workspaceID string) bool {
return workspaceID != "" && workspaceID != WorkspaceIDNone
}

// BuildDescribeCommand builds the describe command for the given config.
Expand All @@ -190,7 +227,7 @@ func BuildLoginCommand(ctx context.Context, profile string, arg u2m.OAuthArgumen
// automatically.
func BuildDescribeCommand(cfg *config.Config) string {
if cfg.Profile != "" {
return "databricks auth describe --profile " + cfg.Profile
return "databricks auth describe --profile " + shellquote.BashArg(cfg.Profile)
}
return "databricks auth describe"
}
62 changes: 61 additions & 1 deletion libs/auth/error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,66 @@ func TestBuildDescribeCommand(t *testing.T) {
)
}

func TestBuildLoginCommand_AppendsWorkspaceID(t *testing.T) {
ctx := t.Context()

t.Run("profile path emits --workspace-id when set", func(t *testing.T) {
cmd := BuildLoginCommand(ctx, "dev", "12345", nil)
assert.Equal(t, "databricks auth login --profile dev --workspace-id 12345", cmd)
})

t.Run("profile path omits --workspace-id when empty", func(t *testing.T) {
cmd := BuildLoginCommand(ctx, "dev", "", nil)
assert.Equal(t, "databricks auth login --profile dev", cmd)
})

t.Run("profile path omits --workspace-id for the 'none' sentinel", func(t *testing.T) {
cmd := BuildLoginCommand(ctx, "dev", WorkspaceIDNone, nil)
assert.Equal(t, "databricks auth login --profile dev", cmd)
})

t.Run("unified host path emits --workspace-id when set", func(t *testing.T) {
oauthArg, err := AuthArguments{
Host: "https://unified.cloud.databricks.com",
AccountID: "acc-123",
DiscoveryURL: "https://unified.cloud.databricks.com/oidc/accounts/acc-123/.well-known/oauth-authorization-server",
}.ToOAuthArgument()
require.NoError(t, err)

cmd := BuildLoginCommand(ctx, "", "ws-456", oauthArg)
assert.Contains(t, cmd, "--account-id acc-123")
assert.Contains(t, cmd, "--workspace-id ws-456")
})

t.Run("workspace host path omits --workspace-id even when provided", func(t *testing.T) {
oauthArg, err := AuthArguments{
Host: "https://adb-123.azuredatabricks.net",
}.ToOAuthArgument()
require.NoError(t, err)

cmd := BuildLoginCommand(ctx, "", "ws-456", oauthArg)
assert.Contains(t, cmd, "--host https://adb-123.azuredatabricks.net")
assert.NotContains(t, cmd, "--workspace-id")
})

t.Run("account host path omits --workspace-id even when provided", func(t *testing.T) {
oauthArg, err := AuthArguments{
Host: "https://accounts.cloud.databricks.com",
AccountID: "acc-123",
}.ToOAuthArgument()
require.NoError(t, err)

cmd := BuildLoginCommand(ctx, "", "ws-456", oauthArg)
assert.Contains(t, cmd, "--account-id acc-123")
assert.NotContains(t, cmd, "--workspace-id")
})

t.Run("profile path shell-quotes profile names with spaces", func(t *testing.T) {
cmd := BuildLoginCommand(ctx, "weird name", "", nil)
assert.Equal(t, "databricks auth login --profile 'weird name'", cmd)
})
}
Comment on lines +28 to +86
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: two coverage gaps in TestBuildLoginCommand_AppendsWorkspaceID:

  1. No negative assertion that AccountOAuthArgument/WorkspaceOAuthArgument paths omit --workspace-id even when one is provided. The production code does this intentionally; a regression test would lock that in.
  2. No shell-quoting test. All the existing cases use safe profile names (dev), so shellquote.BashArg is effectively untested. A profile name like "weird name" would cover the round-trip through the quoter.

Fix: two short table cases — one with WorkspaceOAuthArgument (e.g. classic https://adb-123.azuredatabricks.net) asserting --workspace-id is absent; one with profile = "weird name" asserting the output contains --profile 'weird name'. Both are one-liners.


func TestAuthTypeDisplayName(t *testing.T) {
assert.Equal(t, "Personal Access Token (pat)", AuthTypeDisplayName("pat"))
assert.Equal(t, "OAuth (databricks-cli)", AuthTypeDisplayName("databricks-cli"))
Expand Down Expand Up @@ -241,7 +301,7 @@ func TestEnrichAuthError(t *testing.T) {
"\nHost: https://unified.cloud.databricks.com" +
"\nAuth type: OAuth (databricks-cli)" +
"\n\nNext steps:" +
"\n - Re-authenticate: databricks auth login --host https://unified.cloud.databricks.com --account-id acc-123" +
"\n - Re-authenticate: databricks auth login --host https://unified.cloud.databricks.com --account-id acc-123 --workspace-id ws-456" +
"\n - Check your identity: databricks auth describe" +
"\n - Consider setting up a profile: databricks auth login --profile <name>",
},
Expand Down
Loading