{"record":{"id":"f7c7e30e62e5ee88","repo":"cube-js/cube","slug":"repository-must-be-in-owner-repo-form-got-repo","errorCode":null,"errorMessage":"repository must be in owner/repo form, got `{repo}`","messagePattern":"repository must be in owner/repo form, got `(.+?)`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust/cube-cli/src/commands/github.rs","lineNumber":84,"sourceCode":"    /// Cursor for the next page (from a previous pageInfo.endCursor)\n    #[arg(long)]\n    after: Option<String>,\n}\n\nimpl Page {\n    fn query(&self) -> crate::client::Query {\n        let mut query = Vec::new();\n        util::push(&mut query, \"first\", &self.first);\n        util::push(&mut query, \"after\", &self.after);\n        query\n    }\n}\n\n/// Split an `owner/repo` argument into its two parts.\nfn split_repo(repo: &str) -> Result<(&str, &str)> {\n    repo.split_once('/')\n        .filter(|(owner, name)| !owner.is_empty() && !name.is_empty() && !name.contains('/'))\n        .ok_or_else(|| anyhow::anyhow!(\"repository must be in owner/repo form, got `{repo}`\"))\n}\n\npub async fn command(args: Args, ctx: &Ctx) -> Result<()> {\n    let api = ctx.api()?;\n    match args.cmd {\n        Cmd::Status => {\n            let res = api.get(\"/api/v1/github/status\", &Vec::new()).await?;\n            output::print_json(&res);\n        }\n        Cmd::Installations { page } => {\n            let res = api\n                .get(\"/api/v1/github/installations\", &page.query())\n                .await?;\n            output::print_list(\n                ctx.json,\n                &res,\n                &[(\"INSTALLATION\", \"installationId\"), (\"ACCOUNT\", \"login\")],\n            );","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/rust/cube-cli/src/commands/github.rs#L66-L102","documentation":"`split_repo` validates a GitHub `owner/repo` identifier in cube-cli's github command. It uses `str::split_once('/')` and requires both halves to be non-empty and the repo part to contain no further slashes. If the argument doesn't match that shape, it throws this anyhow error naming the offending input.","triggerScenarios":"Calling `cube-cli github` (Status, etc.) with a repository argument like `\"\"`, `\"owner\"` (no slash), `\"/repo\"`, `\"owner/\"`, or `\"owner/repo/extra\"` — anything failing `split_once('/')` with non-empty parts and no trailing `/`.","commonSituations":"Typing just a repo name forgetting the owner, pasting a full GitHub URL (`https://github.com/owner/repo`) instead of the path form, or a trailing slash from copy-paste.","solutions":["Pass the repository exactly as `owner/repo` (e.g. `cube-tools/cube-cli`).","If you have a full URL, strip the prefix: use the path after `github.com/`.","Trim stray whitespace/trailing slashes from the argument before invoking.","For nested paths, the tool does not support them — use the canonical two-segment form."],"exampleFix":"// before\ncube-cli github status https://github.com/cube-js/cube\n// after\ncube-cli github status cube-js/cube","handlingStrategy":"validation","validationCode":"fn is_owner_repo(repo: &str) -> bool {\n    matches!(repo.split_once('/'), Some((o, n)) if !o.is_empty() && !n.is_empty() && !n.contains('/'))\n}","typeGuard":"fn as_owner_repo(repo: &str) -> Option<(&str, &str)> {\n    repo.split_once('/')\n        .filter(|(o, n)| !o.is_empty() && !n.is_empty() && !n.contains('/'))\n}","tryCatchPattern":null,"preventionTips":["Always pass the `owner/repo` path form, never a full URL","Trim whitespace and trailing slashes from user input","Add shell-completion or argument validation in wrappers around the CLI"],"tags":["cli","input-validation","github"],"backgroundTag":"invalid-argument-format","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}