basecamp/kamal · error · RuntimeError

Bitwarden Secrets Manager CLI is not installed

Error message

Bitwarden Secrets Manager CLI is not installed

What it means

Raised by check_dependencies! in Kamal::Secrets::Adapters::BitwardenSecretsManager after `bws --version 2> /dev/null` exits non-zero ($?.success? false). It is the adapter's pre-flight guard: before any login or fetch attempt, kamal verifies the Bitwarden Secrets Manager CLI binary exists on PATH. Because stderr is discarded, any failure (command not found, broken install, wrong arch binary) collapses into this single message.

Source

Thrown at lib/kamal/secrets/adapters/bitwarden_secrets_manager.rb:59

        elsif secrets[0].end_with?(LIST_ALL_FROM_PROJECT_SUFFIX)
          project = secrets[0].split(LIST_ALL_FROM_PROJECT_SUFFIX).first
          [ "#{LIST_COMMAND} #{project.shellescape}", project ]
        end
      end
    end

    def run_command(command, session: nil)
      full_command = [ "bws", command ].join(" ")
      `#{full_command}`
    end

    def login(account)
      run_command("project list")
      raise RuntimeError, "Could not authenticate to Bitwarden Secrets Manager. Did you set a valid access token?" unless $?.success?
    end

    def check_dependencies!
      raise RuntimeError, "Bitwarden Secrets Manager CLI is not installed" unless cli_installed?
    end

    def cli_installed?
      `bws --version 2> /dev/null`
      $?.success?
    end
end

View on GitHub (pinned to eee0083b38)

Solutions

  1. Install the CLI: `npm install -g @bitwarden/secrets-manager` (provides `bws`), then run `bws --version` to confirm it resolves in the same shell that runs kamal.
  2. If installed but not found, fix PATH (echo $PATH, add the global npm bin dir or /usr/local/bin symlink) and restart the terminal/CI job.
  3. For repeatable environments, add the install step to your Dockerfile/CI script before `kamal secrets pull`.
Defensive patterns

Strategy: validation

Validate before calling

require "open3"

def bws_installed?
  _out, _err, status = Open3.capture3("bws", "--version")
  status.success?
end

abort "Install @bitwarden/secrets-manager (provides bws) first" unless bws_installed?

Prevention

When it happens

Trigger: adapter.fetch(...) is called (Base#fetch line 7 runs check_dependencies!) on a machine where `bws` is not on PATH: never installed, installed only for another user/shell (nvm-style PATH issue), installed after the current shell started, or a non-executable/corrupted binary in PATH.

Common situations: Fresh deploy box or Docker/CI image without the bws package; installing bws via npm globally in a node env manager that kamal's shell does not source; macOS where the CLI was installed under a different Homebrew prefix; renamed binary (e.g. installed as bitwarden-secrets-manager) with no bws symlink.

Related errors


AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21). Data as JSON: /api/errors/a61b90b338d3a05f. Report an issue: GitHub.