{"record":{"id":"3ff04c54893d9766","repo":"jdx/mise","slug":"choose-github-relay-repo-owner-repo-or-github","errorCode":null,"errorMessage":"choose --github-relay-repo OWNER/REPO or --github-relay-all-repos, not both","messagePattern":"choose --github-relay-repo OWNER/REPO or --github-relay-all-repos, not both","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/github_relay.rs","lineNumber":29,"sourceCode":"    repositories: std::collections::BTreeSet<String>,\n    #[cfg(any(unix, test))]\n    all: bool,\n}\n\nimpl Scope {\n    pub(crate) fn from_flags(\n        enabled: bool,\n        repositories: &[String],\n        all: bool,\n    ) -> Result<Option<Self>> {\n        if !enabled {\n            if all || !repositories.is_empty() {\n                bail!(\"repository scope requires --github-relay-read-only\");\n            }\n            return Ok(None);\n        }\n        if all != repositories.is_empty() {\n            bail!(\"choose --github-relay-repo OWNER/REPO or --github-relay-all-repos, not both\");\n        }\n        let repositories: std::collections::BTreeSet<String> = repositories\n            .iter()\n            .map(|repo| repository(repo))\n            .collect::<Result<_>>()?;\n        #[cfg(not(any(unix, test)))]\n        let _ = repositories;\n        Ok(Some(Self {\n            #[cfg(unix)]\n            options: Options::default(),\n            #[cfg(any(unix, test))]\n            repositories,\n            #[cfg(any(unix, test))]\n            all,\n        }))\n    }\n\n    #[cfg(any(unix, test))]","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/github_relay.rs#L11-L47","documentation":"from_flags enforces mutual exclusivity of the two relay scope selections: `all != repositories.is_empty()` means exactly one of --github-relay-all-repos and --github-relay-repo must be given. Passing both (or, after the earlier check, neither) bails with this message.","triggerScenarios":"Invoking from_flags (via the CLI) with both --github-relay-all-repos and one or more --github-relay-repo values set while the relay is enabled.","commonSituations":"Composing relay options from multiple config layers or shell aliases that each append a scope flag; script templates where repo lists are optionally expanded into both flags.","solutions":["Use only --github-relay-all-repos if you want every repository relayed.","Or list explicit repos with repeated --github-relay-repo OWNER/REPO flags and drop --github-relay-all-repos.","If flags come from an alias/script, audit where each flag is appended and keep a single scope source."],"exampleFix":"// before\nmise --github-relay-read-only --github-relay-all-repos --github-relay-repo owner/repo exec -- npm i\n// after\nmise --github-relay-read-only --github-relay-repo owner/repo exec -- npm i","handlingStrategy":"validation","validationCode":"# shell: exactly one scope source\nscope_count=$(( ${RELAY_ALL:+1} + ${RELAY_REPOS:+1} ))\n[[ $scope_count -le 1 ]] || { echo \"use all-repos OR repo list, not both\" >&2; exit 1; }","typeGuard":"fn scope_is_exclusive(all: bool, repos: &[String]) -> bool {\n    all != !repos.is_empty()\n}","tryCatchPattern":"match Scope::from_flags(enabled, repos, all) {\n    Err(e) if e.to_string().contains(\"not both\") => {\n        // drop one of the flags and retry\n    }\n    r => r,\n}","preventionTips":["Build the scope from a single source of truth (one flag-setter in scripts).","If repo lists may be empty, decide explicitly between all-repos and empty scope before flag assembly.","Review shell aliases/CI templates that hardcode --github-relay-all-repos alongside per-repo flags."],"tags":["cli","github-relay","mutually-exclusive","flags"],"backgroundTag":"mutually-exclusive-flags","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}