Skip to content

auth: handle account-only profiles cleanly for workspace and describe commands#5340

Open
simonfaltum wants to merge 4 commits into
mainfrom
simonfaltum/auth-wsid-none-error
Open

auth: handle account-only profiles cleanly for workspace and describe commands#5340
simonfaltum wants to merge 4 commits into
mainfrom
simonfaltum/auth-wsid-none-error

Conversation

@simonfaltum
Copy link
Copy Markdown
Member

@simonfaltum simonfaltum commented May 27, 2026

Why

Two related bugs in a bug bash, both rooted in profiles created with `databricks auth login --skip-workspace` (no `workspace_id`, or the legacy `workspace_id = none` sentinel):

  1. Workspace commands (e.g. `databricks clusters list --profile `) failed with the opaque backend error "Credential was not sent or was of an unsupported type for this API" — the SDK forwarded the literal sentinel as a routing identifier, or sent an unrouted request to the account-plane.
  2. `databricks auth describe --profile ` printed the false-negative `Unable to authenticate: Unable to load OAuth Config` on a perfectly valid profile — describe calls `w.CurrentUser.Me()` after MustAnyClient, which hits the workspace plane without a workspace_id and the backend rejects the call.

Reproduced both against `db-deco-test.databricks.com` with a real `--skip-workspace` profile.

Changes

  • `workspaceClientOrPrompt` detects an account-only profile (`account_id` set + `workspace_id` empty or the legacy "none" sentinel + an explicit `Profile`) before any API call and returns a typed `ErrAccountOnlyProfile` with an actionable message naming the profile.
  • `MustAnyClient` (used by `auth describe` and similar) recognizes `ErrAccountOnlyProfile` and falls through to the account client, so account-only profiles describe cleanly via the account plane.
  • Workspace commands (`MustWorkspaceClient` directly) keep getting the actionable error — they need a workspace.

After the fix on the same `db-deco-test` profile:
```
$ databricks auth describe --profile bug2-test
Host: https://db-deco-test.databricks.com
Account ID: 968367da-...
Authenticated with: databricks-cli
✓ host: https://db-deco-test.databricks.com (from .databrickscfg)
✓ account_id: 968367da-... (from .databrickscfg)
✓ workspace_id: none (from .databrickscfg)
✓ profile: bug2-test (from --profile flag)
✓ auth_type: databricks-cli
...

$ databricks clusters list --profile bug2-test
Error: profile "bug2-test" has no workspace_id set (account-only); this command requires a workspace.
Edit the profile to set workspace_id to a real ID, or pass --profile with a workspace-scoped profile
```

The env-var-only path (no `Profile` set) is intentionally left alone — unified hosts can serve workspace APIs from the account host with just `DATABRICKS_HOST` + `DATABRICKS_ACCOUNT_ID` + a token, and we don't want to reject those.

Test plan

  • Reproduced both bugs against `db-deco-test.databricks.com` with a real `--skip-workspace`-created profile.
  • After the fix: `auth describe --profile bug2-test` succeeds and shows account info; `clusters list --profile bug2-test` gives the actionable error.
  • Existing valid SPOG workspace profile (with `workspace_id`) still works against the same host — no regression.
  • New unit tests: `TestWorkspaceClientOrPromptRejectsAccountOnlyProfile` (both shapes), `TestMustAnyClientFallsThroughOnAccountOnlyProfile`.
  • `go test ./cmd/root/...`, `./task checks`, `./task lint-q`.

Profiles created with `databricks auth login --skip-workspace` are
persisted with the CLI-only `workspace_id = none` sentinel. Running a
workspace command (e.g. `clusters list`) against such a profile failed
with an opaque "Credential was not sent or was of an unsupported type"
error from the auth endpoint, because the SDK forwarded the literal
string "none" as a routing identifier.

Detect the sentinel in `workspaceClientOrPrompt` before any API call and
return a message that names the profile and suggests concrete fixes
(edit the profile to set a real workspace_id, or pass --profile with a
workspace-scoped profile).

Co-authored-by: Isaac
@github-actions
Copy link
Copy Markdown
Contributor

Waiting for approval

Based on git history, these people are best suited to review:

  • @pietern -- recent work in cmd/root/
  • @denik -- recent work in cmd/root/

Eligible reviewers: @Divyansh-db, @chrisst, @hectorcast-db, @mihaimitrea-db, @parthban-db, @rauchy, @renaudhartert-db, @tanmay-db, @tejaskochar-db

Suggestions based on git history. See OWNERS for ownership rules.

PR #5338 stops writing workspace_id = none on --skip-workspace. After it
lands, new account-only profiles have no workspace_id key at all, so the
"= none" check here misses them. Broaden the detection to fire when
cfg.Profile is set, cfg.AccountID is non-empty, and cfg.WorkspaceID is
either empty or the legacy "none" sentinel. Reword the error to talk
about "no workspace_id set" instead of the literal sentinel.

The cfg.Profile guard keeps env-var-only configs targeting a unified
host out of the rejection path (their workspace APIs are served from
the account host and auth resolves end-to-end).

Co-authored-by: Isaac
@eng-dev-ecosystem-bot
Copy link
Copy Markdown
Collaborator

eng-dev-ecosystem-bot commented May 27, 2026

Commit: fa7f3a1

Run: 26512955392

Without this, `databricks auth describe --profile <account-only>` reached
`w.CurrentUser.Me()` in describe.go, which on a SPOG host with
workspace_id absent (or the legacy "none" sentinel) hit the
account-plane and was rejected by the backend with
"Unable to load OAuth Config" — a false negative for a valid profile.

- Promote `accountOnlyProfileError` from a plain `errors.Errorf` to a
  typed `ErrAccountOnlyProfile` so callers can detect it.
- Extend MustAnyClient's fall-through check to include the new type, so
  workspace commands (clusters list, etc.) keep getting the clear
  actionable error from PR #5340 while MustAnyClient callers (auth
  describe, the only one today) recover and describe the profile via
  the account client.

Co-authored-by: Isaac
@simonfaltum simonfaltum changed the title auth: clear error when workspace commands run on an account-only profile auth: handle account-only profiles cleanly for workspace and describe commands May 27, 2026
@simonfaltum simonfaltum temporarily deployed to test-trigger-is May 27, 2026 12:48 — with GitHub Actions Inactive
@simonfaltum simonfaltum temporarily deployed to test-trigger-is May 27, 2026 12:48 — with GitHub Actions Inactive
GPT review pointed out the previous TestMustAnyClientFallsThroughOnAccountOnlyProfile
only verified workspaceClientOrPrompt returned ErrAccountOnlyProfile —
it never called MustAnyClient, so removing the fall-through case from
MustAnyClient wouldn't have failed the test.

Drive it end-to-end: build the same cobra command with --profile,
invoke MustAnyClient, and assert it returns (true, nil) with an
AccountClient on the context.

Co-authored-by: Isaac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants