{"id":"558d5501b4159ba9","repo":"sharkdp/fd","slug":"unable-to-get-shell-from-environment","errorCode":null,"errorMessage":"Unable to get shell from environment","messagePattern":"Unable to get shell from environment","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/cli.rs","lineNumber":781,"sourceCode":"    }\n\n    pub fn strip_cwd_prefix<P: FnOnce() -> bool>(&self, auto_pred: P) -> bool {\n        use self::StripCwdWhen::*;\n        self.no_search_paths()\n            && match self.strip_cwd_prefix.map_or(Auto, |o| o.unwrap_or(Always)) {\n                Auto => auto_pred(),\n                Always => true,\n                Never => false,\n            }\n    }\n\n    #[cfg(feature = \"completions\")]\n    pub fn gen_completions(&self) -> anyhow::Result<Option<Shell>> {\n        self.gen_completions\n            .map(|maybe_shell| match maybe_shell {\n                Some(sh) => Ok(sh),\n                None => {\n                    Shell::from_env().ok_or_else(|| anyhow!(\"Unable to get shell from environment\"))\n                }\n            })\n            .transpose()\n    }\n}\n\n/// Get the default number of threads to use, if not explicitly specified.\nfn default_num_threads() -> NonZeroUsize {\n    // If we can't get the amount of parallelism for some reason, then\n    // default to a single thread, because that is safe.\n    let fallback = NonZeroUsize::MIN;\n    // To limit startup overhead on massively parallel machines, don't use more\n    // than 64 threads.\n    let limit = NonZeroUsize::new(64).unwrap();\n\n    std::thread::available_parallelism()\n        .unwrap_or(fallback)\n        .min(limit)","sourceCodeStart":763,"sourceCodeEnd":799,"githubUrl":"https://github.com/sharkdp/fd/blob/41532d114e2ba565fb5367d606c111b29b96450c/src/cli.rs#L763-L799","documentation":"Thrown by Opts::gen_completions in src/cli.rs:781 when the user runs 'fd --gen-completions' (no shell name) and clap_complete::Shell::from_env() returns None. Shell::from_env reads the $SHELL environment variable and tries to map it to a known Shell variant; if $SHELL is unset or holds an unrecognized value, fd cannot guess which completion script format to emit.","triggerScenarios":"Running 'fd --gen-completions' (double-flag form, Option<Option<Shell>> resolves to Some(None)) in an environment where $SHELL is unset, empty, or contains a binary name not recognized by the Shell enum (e.g. a custom shell wrapper like '/usr/bin/my-fish-fork').","commonSituations":"Minimal Docker/CI containers that strip env vars; running fd under a non-login shell that never set $SHELL; running fd from a systemd unit, cron job, or IDE task runner where the environment is sparse.","solutions":["Pass the shell explicitly: 'fd --gen-completions bash' (or zsh/fish/powershell/elvish).","Export a recognized $SHELL: 'export SHELL=/bin/bash' then re-run 'fd --gen-completions'.","If in CI/containers, set 'ENV SHELL=/bin/sh' in the Dockerfile or pipeline env block before invoking fd."],"exampleFix":"// before\nfd --gen-completions   # fails when $SHELL unset\n\n// after\nfd --gen-completions bash > /etc/bash_completion.d/fd","handlingStrategy":"validation","validationCode":"# before invoking fd --gen-completions, ensure a shell is resolvable\nif [ -z \"$SHELL\" ]; then\n  echo \"SHELL is unset; pass an explicit shell\" >&2\n  exit 1\nfi\nfd --gen-completions \"$SHELL_BASE\"   # or: fd --gen-completions bash","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass an explicit shell to --gen-completions in scripts.","Set SHELL in CI/Dockerfiles so any tool that probes it succeeds.","Treat --gen-completions as a build-time step with a known shell, never a runtime guess."],"tags":["completions","environment","shell","cli-flag"],"analyzedSha":"41532d114e2ba565fb5367d606c111b29b96450c","analyzedAt":"2026-08-06T01:39:28.509Z","schemaVersion":2}