{"record":{"id":"ca13605b1fc256f4","repo":"astrid-runtime/astrid","slug":"update-source-must-be-owner-repo-got-s","errorCode":null,"errorMessage":"update source must be 'owner/repo', got '{s}'","messagePattern":"update source must be 'owner/repo', got '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/self_update/mod.rs","lineNumber":87,"sourceCode":"\n/// GitHub API base URL. `ASTRID_UPDATE_API` overrides it so the flow can be\n/// rehearsed against a local/staging mock server.\npub(super) fn api_base() -> String {\n    std::env::var(\"ASTRID_UPDATE_API\").unwrap_or_else(|_| \"https://api.github.com\".to_string())\n}\n\n/// Resolve release discovery: explicit `--source`, environment, then default.\n/// Mirrors and mocks must still serve archives signed by Astrid's exact identity.\nfn resolve_repo(source: Option<&str>) -> anyhow::Result<(String, String)> {\n    let spec = source\n        .map(str::to_owned)\n        .or_else(|| std::env::var(\"ASTRID_UPDATE_REPO\").ok());\n    match spec {\n        Some(s) => {\n            let (owner, repo) = s\n                .split_once('/')\n                .filter(|(o, r)| !o.is_empty() && !r.is_empty())\n                .ok_or_else(|| anyhow::anyhow!(\"update source must be 'owner/repo', got '{s}'\"))?;\n            Ok((owner.to_string(), repo.to_string()))\n        },\n        None => Ok((DEFAULT_ORG.to_string(), DEFAULT_REPO.to_string())),\n    }\n}\n\n/// Map the current platform to the GitHub release asset target triple.\nfn platform_target() -> anyhow::Result<&'static str> {\n    platform_target_for(\n        std::env::consts::OS,\n        std::env::consts::ARCH,\n        compile_time_target_env(),\n    )\n}\n\nconst fn compile_time_target_env() -> &'static str {\n    if cfg!(target_env = \"gnu\") {\n        \"gnu\"","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/self_update/mod.rs#L69-L105","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nASTRID_UPDATE_REPO=https://github.com/acme/astrid astrid self update\n// after\nASTRID_UPDATE_REPO=acme/astrid astrid self update","handlingStrategy":"validation","validationCode":"// validate before invoking\nconst RE = /^[^/\\s]+\\/[^/\\s]+$/;\nif (process.env.ASTRID_UPDATE_REPO && !RE.test(process.env.ASTRID_UPDATE_REPO)) {\n  throw new Error(\"ASTRID_UPDATE_REPO must be 'owner/repo'\");\n}","typeGuard":"fn parse_repo_spec(s: &str) -> Option<(&str, &str)> {\n    s.split_once('/').filter(|(o, r)| !o.is_empty() && !r.is_empty())\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["cli","self-update","argument-format","env-var"],"backgroundTag":"invalid-argument-format","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}