{"record":{"id":"e1118db9e93396e2","repo":"basecamp/kamal","slug":"could-not-authenticate-to-bitwarden-secrets-manage","errorCode":null,"errorMessage":"Could not authenticate to Bitwarden Secrets Manager. Did you set a valid access token?","messagePattern":"Could not authenticate to Bitwarden Secrets Manager\\. Did you set a valid access token\\?","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"lib/kamal/secrets/adapters/bitwarden_secrets_manager.rb","lineNumber":55,"sourceCode":"    def extract_command_and_project(secrets)\n      if secrets.length == 1\n        if secrets[0] == LIST_ALL_SELECTOR\n          [ LIST_COMMAND, nil ]\n        elsif secrets[0].end_with?(LIST_ALL_FROM_PROJECT_SUFFIX)\n          project = secrets[0].split(LIST_ALL_FROM_PROJECT_SUFFIX).first\n          [ \"#{LIST_COMMAND} #{project.shellescape}\", project ]\n        end\n      end\n    end\n\n    def run_command(command, session: nil)\n      full_command = [ \"bws\", command ].join(\" \")\n      `#{full_command}`\n    end\n\n    def login(account)\n      run_command(\"project list\")\n      raise RuntimeError, \"Could not authenticate to Bitwarden Secrets Manager. Did you set a valid access token?\" unless $?.success?\n    end\n\n    def check_dependencies!\n      raise RuntimeError, \"Bitwarden Secrets Manager CLI is not installed\" unless cli_installed?\n    end\n\n    def cli_installed?\n      `bws --version 2> /dev/null`\n      $?.success?\n    end\nend\n","sourceCodeStart":37,"sourceCodeEnd":67,"githubUrl":"https://github.com/basecamp/kamal/blob/eee0083b38661c3707c6b6052cc89e85038a096c/lib/kamal/secrets/adapters/bitwarden_secrets_manager.rb#L37-L67","documentation":"Kamal's Bitwarden Secrets Manager adapter raises this in #login after running `bws project list` and observing a non-zero exit status ($?.success? is false). The bws CLI authenticates solely through the machine-account access token it reads from the environment (BWS_ACCESS_TOKEN), so a missing, malformed, revoked, or expired token makes every command fail. The error surfaces during Kamal::Secrets::Adapters::BitwardenSecretsManager#fetch, after check_dependencies! has already confirmed the CLI is installed.","triggerScenarios":"Calling adapter.fetch(secrets, account: ...) (directly or via `kamal secrets pull` with secrets adapter bitwarden_secrets_manager) when: BWS_ACCESS_TOKEN is unset in the shell running kamal; the token was copied with stray whitespace/quotes or truncated; the machine account was deleted or its access token revoked in the Bitwarden admin console; or the token belongs to a different organization/server than bws is pointed at. run_command(\"project list\") returns non-zero and the raise fires unless $?.success?.","commonSituations":"CI pipelines where the token lives in a CI secret variable that was never exported; rotating tokens after a security review and forgetting to update the local .env/kamal env; self-hosted Bitwarden with a BWS server URL mismatch; token generated for a user account instead of a machine account (bws only accepts machine-account access tokens).","solutions":["Create a machine account and access token in the Bitwarden Secrets Manager admin console, then export it: export BWS_ACCESS_TOKEN=<token> (put it in the environment kamal runs in, e.g. .kamal/secrets or CI masked variables).","Verify the token works standalone before blaming kamal: `bws project list` must print JSON; if it errors, fix the token/CLI first.","Check the token was not truncated or wrapped in quotes when pasted (re-copy from the console; tokens are long base64-ish strings).","If the machine account or token was revoked, generate a new access token and update every environment that runs kamal."],"exampleFix":"# before: token missing/expired, `kamal secrets pull` raises\n#   Could not authenticate to Bitwarden Secrets Manager...\n\n# after: provision and export a machine-account token\n#   export BWS_ACCESS_TOKEN=\"0000...\"\nbws project list  # sanity check: must print JSON\nkamal secrets pull","handlingStrategy":"try-catch","validationCode":"require \"open3\"\n\ndef bws_authenticated?\n  _out, _err, status = Open3.capture3(\"bws\", \"project\", \"list\",\n                                      { BWS_ACCESS_TOKEN: ENV.fetch(\"BWS_ACCESS_TOKEN\", \"\") })\n  status.success?\nend\n\nraise \"Set a valid BWS_ACCESS_TOKEN before deploying\" unless bws_authenticated?","typeGuard":null,"tryCatchPattern":"begin\n  secrets = adapter.fetch(%w[RAILS_MASTER_KEY], account: nil)\nrescue RuntimeError => e\n  raise \"Bitwarden auth failed: check BWS_ACCESS_TOKEN (rotated/revoked?) — #{e.message}\" if e.message.include?(\"authenticate to Bitwarden\")\n  raise\nend","preventionTips":["Provision BWS_ACCESS_TOKEN as a masked CI variable and assert it is present (ENV.key?('BWS_ACCESS_TOKEN')) before running kamal.","Add a pre-deploy probe (`bws project list >/dev/null`) to fail with a clearer message than the adapter's generic raise.","Track token rotation dates; regenerate machine-account tokens and update all environments together."],"tags":["ruby","kamal","bitwarden","secrets","authentication","access-token","env-var","cli-exit-code"],"backgroundTag":"invalid-access-token","analyzedSha":"eee0083b38661c3707c6b6052cc89e85038a096c","analyzedAt":"2026-08-21T15:17:22.045Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}