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
- Set the repo spec to plain 'owner/repo' form, e.g. 'acme/astrid', not a full URL.
- Unset ASTRID_UPDATE_REPO (or remove it from shell profile) to fall back to the default repository.
- If pointing at a GitHub URL, strip 'https://github.com/' and any trailing '.git' first.
- 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
- Always use bare 'owner/repo', never full URLs.
- Audit shell profiles for stale ASTRID_UPDATE_REPO exports.
- Document the expected format wherever the override is used.
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
- ASTRID_ENFORCED_DISTRO must not be empty
- astrid init cannot override the operator-enforced distro in
- --git-history requires non-empty NAME=REPO::RELATIVE_PATH
- {name} not found. Ensure it is installed alongside the astri
- {name} is not installed beside the Astrid CLI; refusing a PA
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/ca13605b1fc256f4.
Report an issue: GitHub.