tinyhumansai/openhuman · error
provider is required
Error message
provider is required
What it means
Thrown by BackendOAuthClient::login_url when the provider argument is empty after trimming whitespace and stripping leading/trailing slashes. The provider string becomes a path segment ("auth/{provider}/login"), so an empty value would build a malformed login URL; the guard fails fast instead. It is a pure caller-input check — no network is touched.
Source
Thrown at src/api/rest.rs:452
/// drive a non-JSON request shape (e.g. `multipart/form-data` uploads
/// for cloud STT) without re-implementing TLS/proxy plumbing.
pub fn raw_client(&self) -> &Client {
&self.client
}
/// Resolve a backend-relative path against the configured base URL.
/// Mirrors what `authed_json` does internally so callers using
/// `raw_client()` don't have to assemble URLs by hand.
pub fn url_for(&self, path: &str) -> Result<Url> {
self.base
.join(path.trim_start_matches('/'))
.with_context(|| format!("build URL for {path}"))
}
/// Returns the URL for initiating a login flow for a specific provider.
pub fn login_url(&self, provider: &str) -> Result<Url> {
let p = provider.trim().trim_matches('/');
anyhow::ensure!(!p.is_empty(), "provider is required");
self.base
.join(&format!("auth/{p}/login"))
.context("build login URL")
}
/// Initiates an OAuth connection flow for the current user and a specific provider.
pub async fn connect(
&self,
provider: &str,
bearer_jwt: &str,
skill_id: Option<&str>,
response_type: Option<&str>,
encryption_mode: Option<&str>,
) -> Result<ConnectResponse> {
let p = provider.trim().trim_matches('/');
anyhow::ensure!(!p.is_empty(), "provider is required");
let query = {
let mut serializer = url::form_urlencoded::Serializer::new(String::new());View on GitHub (pinned to a221052e0d)
Solutions
- Pass a concrete provider id such as "telegram", "google", "discord"
- Validate the provider selection at the UI/CLI boundary before invoking login_url
- Default to a known provider when the field is optional in your flow
Example fix
// before
let url = client.login_url(&selected_provider)?; // selected_provider = ""
// after
let provider = selected_provider.trim().trim_matches('/');
anyhow::ensure!(!provider.is_empty(), "select a provider first");
let url = client.login_url(provider)?; Defensive patterns
Strategy: validation
Validate before calling
let provider = provider.trim().trim_matches('/');
anyhow::ensure!(!provider.is_empty(), "provider must be selected before building login URL");
let url = client.login_url(provider)?; Type guard
fn is_provider_slug(s: &str) -> bool {
let t = s.trim().trim_matches('/');
!t.is_empty() && t.chars().all(|c| c.is_ascii_alphanumeric() || c == '-')
} Prevention
- Make provider an enum or a validated string at the UI/CLI boundary, not a free text field
- Default the dropdown to a concrete provider so the unselected state never reaches the call
When it happens
Trigger: Calling login_url(""), login_url(" "), or login_url("/") — e.g. the provider slug came from a config field, CLI flag, or UI selection that was never filled in.
Common situations: A provider dropdown in the UI submitted with no selection, a config template shipping an empty [[provider]] entry, or a default provider constant that was renamed to an empty string.
Related errors
- OPENAI_CODEX_OAUTH_MISSING_CALLBACK_URL
- API base URL must be an absolute http(s) URL with host
- login token is required
- channel is required
- integrationId must be a 24-char hex id
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/0f1fad55681d9d6f.
Report an issue: GitHub.