{"record":{"id":"4aca7d86cfc409d2","repo":"jdx/mise","slug":"network-git-calls-do-not-accept-a-work-tree-alter","errorCode":null,"errorMessage":"network Git calls do not accept a work tree, alternate index, or stdin","messagePattern":"network Git calls do not accept a work tree, alternate index, or stdin","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/git.rs","lineNumber":875,"sourceCode":"            .stderr(std::process::Stdio::inherit())\n            .stdin(std::process::Stdio::null());\n        cmd.status()\n            .wrap_err_with(|| format!(\"failed to run {}\", describe_plumbing(&cmd)))\n    }\n\n    /// Runs the call and returns its trimmed stdout.\n    pub(crate) fn output_str(&self, call: PlumbingCall<'_>) -> Result<String> {\n        let out = self.output(call)?;\n        Ok(String::from_utf8_lossy(&out).trim().to_string())\n    }\n\n    /// Runs a network command (`fetch`, `push`, `ls-remote`) against this\n    /// repository with the user's normal git configuration: credential\n    /// helpers, ssh settings, and URL rewrites apply, while hooks, filters,\n    /// and aliases still cannot act on mise's repository because only\n    /// plumbing runs here. Prompts are disabled when nobody is attending.\n    pub(crate) fn network_output(&self, call: PlumbingCall<'_>) -> Result<std::process::Output> {\n        eyre::ensure!(\n            call.work_tree.is_none() && call.index_file.is_none() && call.stdin.is_none(),\n            \"network Git calls do not accept a work tree, alternate index, or stdin\"\n        );\n        let git =\n            plumbing_binary().ok_or_else(|| eyre!(\"no unattended git executable is available\"))?;\n        let mut cmd = std::process::Command::new(git);\n        sanitize_git_command(&mut cmd);\n        if !console::user_attended_stderr() {\n            cmd.env(\"GIT_TERMINAL_PROMPT\", \"0\");\n        }\n        cmd.args([\n            \"-c\",\n            &github_credential_config(\"github.com\"),\n            \"-c\",\n            &github_credential_config(\"github.com:443\"),\n        ]);\n        cmd.env(\"GIT_OPTIONAL_LOCKS\", \"0\")\n            .env(\"LC_ALL\", \"C\")","sourceCodeStart":857,"sourceCodeEnd":893,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/git.rs#L857-L893","documentation":"mise's git plumbing wrapper distinguishes local plumbing calls from network commands (fetch/push/ls-remote). Network calls run with the user's normal git config but must not carry a work tree, alternate index file, or stdin, since those only make sense for repository-local operations. Passing any of them to network_output is a programming error and is rejected up front.","triggerScenarios":"Calling Git::network_output with a PlumbingCall that has work_tree, index_file, or stdin set — i.e., misuse of the internal API when wiring fetch/push/ls-remote.","commonSituations":"Refactoring plumbing call construction and reusing a local-call builder for network operations; copying a call struct that still carries an index file or stdin payload from a prior local command.","solutions":["Construct the PlumbingCall for network commands without work_tree/index_file/stdin","Use the local plumbing entry point instead if the call genuinely needs a work tree or index","Ensure the call is one of the supported network subcommands (fetch, push, ls-remote)","Review the call site that builds the PlumbingCall and strip local-only fields"],"exampleFix":"// before\nrepo.network_output(PlumbingCall { subcommand: \"fetch\", work_tree: Some(repo.path), .. })\n// after\nrepo.network_output(PlumbingCall { subcommand: \"fetch\", work_tree: None, index_file: None, stdin: None, .. })","handlingStrategy":"type-guard","validationCode":"fn assert_network_call(call: &PlumbingCall) {\n    assert!(call.work_tree.is_none() && call.index_file.is_none() && call.stdin.is_none(),\n        \"network calls must not carry local-only fields\");\n}","typeGuard":"fn is_network_call(call: &PlumbingCall) -> bool {\n    matches!(call.subcommand, \"fetch\" | \"push\" | \"ls-remote\")\n        && call.work_tree.is_none()\n        && call.index_file.is_none()\n        && call.stdin.is_none()\n}","tryCatchPattern":null,"preventionTips":["Use dedicated constructors for network vs local plumbing calls","Never reuse a local-call builder when wiring fetch/push/ls-remote","Add unit tests asserting network calls have no work_tree/index/stdin","Review PlumbingCall struct literals for leftover local-only fields"],"tags":["git","internal-api","plumbing","network"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}