astrid-runtime/astrid · error

update source must be 'owner/repo', got '{s}'

Error message

update source must be 'owner/repo', got '{s}'

What it means

resolve_repo turns a --repo/--from flag value or ASTRID_UPDATE_REPO env var into an (owner, repo) pair for GitHub release lookups. If the value is set but not exactly 'owner/repo' (missing slash, empty owner or repo), it throws. When unset, it falls back to the built-in DEFAULT_ORG/DEFAULT_REPO.

Source

Thrown at crates/astrid-cli/src/commands/self_update/mod.rs:87

/// GitHub API base URL. `ASTRID_UPDATE_API` overrides it so the flow can be
/// rehearsed against a local/staging mock server.
pub(super) fn api_base() -> String {
    std::env::var("ASTRID_UPDATE_API").unwrap_or_else(|_| "https://api.github.com".to_string())
}

/// Resolve release discovery: explicit `--source`, environment, then default.
/// Mirrors and mocks must still serve archives signed by Astrid's exact identity.
fn resolve_repo(source: Option<&str>) -> anyhow::Result<(String, String)> {
    let spec = source
        .map(str::to_owned)
        .or_else(|| std::env::var("ASTRID_UPDATE_REPO").ok());
    match spec {
        Some(s) => {
            let (owner, repo) = s
                .split_once('/')
                .filter(|(o, r)| !o.is_empty() && !r.is_empty())
                .ok_or_else(|| anyhow::anyhow!("update source must be 'owner/repo', got '{s}'"))?;
            Ok((owner.to_string(), repo.to_string()))
        },
        None => Ok((DEFAULT_ORG.to_string(), DEFAULT_REPO.to_string())),
    }
}

/// Map the current platform to the GitHub release asset target triple.
fn platform_target() -> anyhow::Result<&'static str> {
    platform_target_for(
        std::env::consts::OS,
        std::env::consts::ARCH,
        compile_time_target_env(),
    )
}

const fn compile_time_target_env() -> &'static str {
    if cfg!(target_env = "gnu") {
        "gnu"

View on GitHub (pinned to affd8760f4)

Solutions

  1. Set the repo spec to plain 'owner/repo' form, e.g. 'acme/astrid', not a full URL.
  2. Unset ASTRID_UPDATE_REPO (or remove it from shell profile) to fall back to the default repository.
  3. If pointing at a GitHub URL, strip 'https://github.com/' and any trailing '.git' first.
  4. Retry the update or update check after correcting the value.

Example fix

// before
ASTRID_UPDATE_REPO=https://github.com/acme/astrid astrid self update
// after
ASTRID_UPDATE_REPO=acme/astrid astrid self update
Defensive patterns

Strategy: validation

Validate before calling

// validate before invoking
const RE = /^[^/\s]+\/[^/\s]+$/;
if (process.env.ASTRID_UPDATE_REPO && !RE.test(process.env.ASTRID_UPDATE_REPO)) {
  throw new Error("ASTRID_UPDATE_REPO must be 'owner/repo'");
}

Type guard

fn parse_repo_spec(s: &str) -> Option<(&str, &str)> {
    s.split_once('/').filter(|(o, r)| !o.is_empty() && !r.is_empty())
}

Prevention

When it happens

Trigger: self update run with a malformed repo spec like 'astrid' (no slash), '/repo', 'owner/', or 'a/b/c' via the flag or the ASTRID_UPDATE_REPO environment variable; check_for_update_cached reading the same malformed env var.

Common situations: Typo when pointing updates at a fork (forgetting the owner, trailing slash, full URL pasted instead of owner/repo); stale ASTRID_UPDATE_REPO exported in shell profile from an old experiment.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/ca13605b1fc256f4. Report an issue: GitHub.