zeroclaw-labs/zeroclaw · error · anyhow::Error

git channel provider `{provider}` requires channels.git.<ali

Error message

git channel provider `{provider}` requires channels.git.<alias>.api_base_url - the instance's API base URL including /api/v1, e.g. `https://git.example.org/api/v1` (or `https://gitea.com/api/v1` for the public Gitea service). No default host is assumed because API requests carry the access token

What it means

For the gitea and forgejo providers, build_provider requires channels.git.<alias>.api_base_url — the instance's API base URL including the /api/v1 suffix (e.g. https://git.example.org/api/v1, or https://gitea.com/api/v1 for the public service). No default host is assumed because API requests carry the access token, which is instance-scoped. A missing, empty, or whitespace-only value bails at channel construction.

Source

Thrown at crates/zeroclaw-channels/src/git/channel.rs:113

                anyhow::bail!(
                    "git channel provider `github` requires the `provider-github` feature"
                );
            }
        }
        provider @ ("gitea" | "forgejo") => {
            #[cfg(feature = "provider-gitea")]
            {
                // Fail closed before any HTTP client exists: every request
                // attaches `access_token` as a bearer credential, so guessing
                // a default host would send the token to an endpoint the
                // operator never named (e.g. a Forgejo PAT to gitea.com).
                let Some(api_base_url) = cfg
                    .api_base_url
                    .as_deref()
                    .map(str::trim)
                    .filter(|s| !s.is_empty())
                else {
                    anyhow::bail!(
                        "git channel provider `{provider}` requires \
                         channels.git.<alias>.api_base_url - the instance's API base \
                         URL including /api/v1, e.g. `https://git.example.org/api/v1` \
                         (or `https://gitea.com/api/v1` for the public Gitea service). \
                         No default host is assumed because API requests carry the \
                         access token"
                    );
                };
                Ok(Box::new(super::providers::gitea::GiteaProvider::new(
                    api_base_url.to_string(),
                    cfg.access_token.clone(),
                    cfg.proxy_url.clone(),
                )))
            }
            #[cfg(not(feature = "provider-gitea"))]
            {
                anyhow::bail!(
                    "git channel provider `{provider}` requires the `provider-gitea` feature"

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Set api_base_url to the instance's API root including /api/v1, e.g. https://git.example.org/api/v1
  2. For the public Gitea service use https://gitea.com/api/v1
  3. Use the bare API base — no trailing slash, no /repos suffix
  4. Make sure the host matches the instance the access token belongs to, since the token travels with every API request

Example fix

# before
[channels.git.mine]
provider = "forgejo"
api_base_url = "" # empty → construction bails

# after
[channels.git.mine]
provider = "forgejo"
api_base_url = "https://git.example.org/api/v1"
Defensive patterns

Strategy: validation

Validate before calling

// Rust — fail fast at config load
if matches!(provider.as_str(), "gitea" | "forgejo") {
    let base = cfg.api_base_url.as_deref().map(str::trim).unwrap_or("");
    if base.is_empty() {
        anyhow::bail!(
            "api_base_url is required for {provider}; e.g. https://git.example.org/api/v1"
        );
    }
    if !base.trim_end_matches('/').ends_with("/api/v1") {
        anyhow::bail!("api_base_url should include the /api/v1 suffix: {base}");
    }
}

Prevention

When it happens

Trigger: provider = "gitea" or "forgejo" with api_base_url absent, empty, or whitespace-only (the code trims before checking). Note construction only checks non-emptiness: a value without /api/v1 passes construction but fails later with API 404s.

Common situations: Self-hosted Gitea/Forgejo where the operator assumed a default host exists; copying the web UI URL instead of the API path; forgetting the /api/v1 suffix; token from a different instance than the configured host.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/2f028bfcf2fa0c54. Report an issue: GitHub.