Skip to content

config: pin cfg.Profile on the legacy [DEFAULT] fallback#1690

Open
simonfaltum wants to merge 1 commit into
mainfrom
simonfaltum/profile-fallback-pins-cfg-profile
Open

config: pin cfg.Profile on the legacy [DEFAULT] fallback#1690
simonfaltum wants to merge 1 commit into
mainfrom
simonfaltum/profile-fallback-pins-cfg-profile

Conversation

@simonfaltum
Copy link
Copy Markdown
Member

Changes

The config-file loader's resolveProfile distinguishes "the caller named this profile" from "we silently fell back to [DEFAULT]" via the isFallback return. On a fallback, Configure loaded the section's values into cfg but deliberately left cfg.Profile empty (the if !isFallback { cfg.Profile = profile } gate at config/config_file.go:103-105). The intent was preserving the caller's "I didn't pick a profile" signal.

That signal turns out to be a footgun for consumers that derive a per-profile identifier from cfg.Profile. The Databricks CLI's U2M OAuth cache, for example, uses cfg.Profile as the cache key. When the CLI runs databricks auth login --profile DEFAULT --host ... it writes a token under cache key "DEFAULT". When the user later runs databricks auth describe with no flag, the loader silently falls back to [DEFAULT] but cfg.Profile stays empty, so the OAuthArgument's cache key drifts to the host URL and the lookup misses. The bug is masked when the CLI also dual-writes to a host-keyed entry (its legacy plaintext mode); under secure storage it surfaces as cache: token not found or, when a stale host-key entry exists, InvalidRefreshTokenError.

This PR drops the !isFallback gate so cfg.Profile always reflects the section the loader actually read. isFallback is still load-bearing earlier in Configure (lines 91-95): a missing [DEFAULT] section is tolerated only on fallback, and that behavior is preserved.

This is a self-consistency fix for the SDK and a defense-in-depth followup to the CLI's own resolveDefaultProfile change (databricks/cli#5280). After the SDK bump, the CLI's pre-population becomes redundant but harmless.

Linked: databricks/cli#5280 (the CLI-side fix that lands ahead of this).

Tests

  • New TestConfigFile_LegacyFallbackSetsResolvedProfileName asserts cfg.Profile == "DEFAULT" on the legacy fallback path.
  • Existing config tests pass unchanged; the previously-untested cfg.Profile value on the legacy fallback was the bug.
  • make fmt, make lint, make test clean locally.

This pull request and its description were written by Isaac.

Signed-off-by: Isaac

The config-file loader's resolveProfile distinguishes "the caller named
this profile" from "we silently fell back to [DEFAULT]" via the
isFallback return. On a fallback, the loader loaded the section's
values into cfg but deliberately left cfg.Profile empty (the
`if !isFallback { cfg.Profile = profile }` gate). The intent was
preserving the caller's "I didn't pick a profile" signal.

That signal turns out to be a footgun for consumers that derive a
per-profile identifier from cfg.Profile. The Databricks CLI's U2M
OAuth cache, for example, uses cfg.Profile as the cache key. When the
CLI calls `auth login --profile DEFAULT --host ...` it writes a token
under cache key "DEFAULT". When the user later runs `auth describe`
with no flag, the loader silently falls back to [DEFAULT] but
cfg.Profile stays empty, so the OAuthArgument's cache key drifts to
the host URL and the lookup misses. The bug is masked when the CLI
also dual-writes to a host-keyed entry (its legacy plaintext mode);
under secure storage it surfaces as "cache: token not found" or, when
a stale host-key entry exists, InvalidRefreshTokenError.

Drop the !isFallback gate so cfg.Profile always reflects the section
the loader actually read. isFallback is still load-bearing earlier in
Configure: a missing section is tolerated only on fallback.

This is a self-consistency fix for the SDK and a defense-in-depth
followup to the CLI's own resolveDefaultProfile change. After the SDK
bump, the CLI's pre-population becomes redundant but harmless.

Co-authored-by: Isaac
Signed-off-by: simon <simon.faltum@databricks.com>
@github-actions
Copy link
Copy Markdown

If integration tests don't run automatically, an authorized user can run them manually by following the instructions below:

Trigger:
go/deco-tests-run/sdk-go

Inputs:

  • PR number: 1690
  • Commit SHA: 3db5fc056bcb996278d3d04c713ac74bff2b5f56

Checks will be approved automatically on success.

@simonfaltum simonfaltum deployed to test-trigger-is May 20, 2026 12:40 — with GitHub Actions Active
@simonfaltum simonfaltum requested a review from pietern May 20, 2026 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant