aaif-goose/goose · error

Databricks OAuth token provider is not configured

Error message

Databricks OAuth token provider is not configured

What it means

DatabricksAuthProvider was built in OAuth mode (DatabricksAuth::OAuth { host, client_id, redirect_url, scopes }) but its oauth_token_provider field is None, so get_auth_header() has no callback capable of minting/refreshing a token and bails immediately. goose's own databricks and databricks_v2 provider definitions always pass Some(oauth_token_provider(...)); only hand-rolled constructions of DatabricksAuthProvider can hit this.

Source

Thrown at crates/goose-providers/src/databricks_auth.rs:80

                    None => {
                        let fresh = self
                            .token_resolver
                            .as_ref()
                            .and_then(|resolve| resolve())
                            .unwrap_or_else(|| original.clone());
                        *self.token_cache.lock().unwrap() = Some(fresh.clone());
                        fresh
                    }
                }
            }
            DatabricksAuth::OAuth {
                host,
                client_id,
                redirect_url,
                scopes,
            } => {
                let Some(provider) = &self.oauth_token_provider else {
                    anyhow::bail!("Databricks OAuth token provider is not configured")
                };
                provider(
                    host.clone(),
                    client_id.clone(),
                    redirect_url.clone(),
                    scopes.clone(),
                )
                .await?
            }
        };
        Ok(("Authorization".to_string(), format!("Bearer {token}")))
    }
}

View on GitHub (pinned to 3810898a74)

Solutions

  1. Pass a token-provider closure when constructing: databricks.rs and databricks_v2.rs take Option<DatabricksOauthTokenProvider>; supply Some(provider) whenever auth is OAuth — see oauth_token_provider() in databricks_def.rs for a reference implementation
  2. Prefer the high-level constructors (databricks::from_config, databricks_v2::...) which wire the provider for you
  3. If you only have a PAT, use DatabricksAuth::Token(token) instead of OAuth mode

Example fix

// before
let auth_method = AuthMethod::Custom(Box::new(DatabricksAuthProvider {
    auth: DatabricksAuth::oauth(host.clone()),
    token_cache: Arc::new(Mutex::new(None)),
    oauth_token_provider: None, // -> bails on first request
    token_resolver: None,
}));

// after
let auth_method = AuthMethod::Custom(Box::new(DatabricksAuthProvider {
    auth: DatabricksAuth::oauth(host.clone()),
    token_cache: Arc::new(Mutex::new(None)),
    oauth_token_provider: Some(my_token_provider), // Fn(host, id, redirect, scopes) -> Future<Result<String>>
    token_resolver: None,
}));
Defensive patterns

Strategy: type-guard

Validate before calling

fn oauth_auth_ready(auth: &DatabricksAuth, provider: &Option<DatabricksOauthTokenProvider>) -> bool {
    !(matches!(auth, DatabricksAuth::OAuth { .. }) && provider.is_none())
}

Type guard

fn needs_oauth_provider(auth: &DatabricksAuth) -> bool {
    matches!(auth, DatabricksAuth::OAuth { .. })
}
// Guard at construction:
if needs_oauth_provider(&auth) {
    anyhow::ensure!(oauth_provider.is_some(), "OAuth auth requires a token provider closure");
}

Try / catch

match provider.get_auth_header().await {
    Err(e) if e.to_string().contains("token provider is not configured") =>
        return Err(anyhow!("construction bug: build this provider via databricks::from_config which wires OAuth")),
    r => r?,
}

Prevention

When it happens

Trigger: Constructing DatabricksAuthProvider directly (struct literal or via a builder that leaves oauth_token_provider unset) with auth = DatabricksAuth::oauth(host), then issuing any request, which calls get_auth_header().

Common situations: Library users embedding goose who copy the struct definition instead of calling databricks::from_config / databricks_v2 constructors; code paths that choose OAuth when no UI/daemon is available to complete the OAuth flow (the provider closure must exist regardless of whether a flow can run).

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/6688f367ce8c2611. Report an issue: GitHub.