sharkdp/fd · warning · anyhow::Error

Unable to get shell from environment

Error message

Unable to get shell from environment

What it means

Thrown when fd's --gen-completions flag is invoked with no shell argument and the active shell cannot be auto-detected from the environment. fd delegates detection to clap_complete::Shell::from_env(), which inspects $SHELL (Unix) or registry/env conventions (Windows); if that returns None, generation cannot proceed. This only fires under the 'completions' cargo feature and only for the bare --gen-completions form.

Solutions

  1. Pass the shell explicitly: `fd --gen-completions bash` (or zsh/fish/powershell/elvish).
  2. Export $SHELL before running: `SHELL=/bin/bash fd --gen-completions`.
  3. If scripting in an unknown environment, always specify the target shell as an argument rather than relying on auto-detection.

Example fix

# before (fails when $SHELL unset)
fd --gen-completions

# after (explicit shell)
fd --gen-completions bash
Defensive patterns

Strategy: validation

Validate before calling

if [ -z "$SHELL" ]; then
  # caller supplies the shell explicitly
  fd --gen-completions bash
else
  fd --gen-completions
fi

Prevention

When it happens

Trigger: Running `fd --gen-completions` (no value) on a system where $SHELL is unset/empty, or in a container/cron/launchd context that strips environment variables. The code path is cli.rs:781, reached via Opts::gen_completions() when gen_completions is Some(None).

Common situations: CI runners and minimal Docker images that don't export $SHELL; systemd units; cron jobs; chroot/sandbox environments; macOS GUI-launched processes that lack a login shell env.

Related errors


AI-assisted analysis of sharkdp/fd@b422e5d8c9 (2026-08-09). Data as JSON: /api/errors/558d5501b4159ba9. Report an issue: GitHub.

Appendix: source

Thrown at src/cli.rs:782

    }

    pub fn strip_cwd_prefix<P: FnOnce() -> bool>(&self, auto_pred: P) -> bool {
        use self::StripCwdWhen::*;
        self.no_search_paths()
            && match self.strip_cwd_prefix.map_or(Auto, |o| o.unwrap_or(Always)) {
                Auto => auto_pred(),
                Always => true,
                Never => false,
            }
    }

    #[cfg(feature = "completions")]
    pub fn gen_completions(&self) -> anyhow::Result<Option<Shell>> {
        self.gen_completions
            .map(|maybe_shell| match maybe_shell {
                Some(sh) => Ok(sh),
                None => {
                    Shell::from_env().ok_or_else(|| anyhow!("Unable to get shell from environment"))
                }
            })
            .transpose()
    }
}

/// Get the default number of threads to use, if not explicitly specified.
fn default_num_threads() -> NonZeroUsize {
    // If we can't get the amount of parallelism for some reason, then
    // default to a single thread, because that is safe.
    let fallback = NonZeroUsize::MIN;
    // To limit startup overhead on massively parallel machines, don't use more
    // than 64 threads.
    let limit = NonZeroUsize::new(64).unwrap();

    std::thread::available_parallelism()
        .unwrap_or(fallback)
        .min(limit)

View on GitHub (pinned to b422e5d8c9)