{"record":{"id":"eab78a1603d71807","repo":"basecamp/kamal","slug":"could-not-read-secrets-from-aws-secrets-manager","errorCode":null,"errorMessage":"Could not read #{secrets} from AWS Secrets Manager","messagePattern":"Could not read #(.+?) from AWS Secrets Manager","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"lib/kamal/secrets/adapters/aws_secrets_manager.rb","lineNumber":37,"sourceCode":"              results[\"#{secret_name}/#{key}\"] = stringify_secret_value(value)\n            end\n          else\n            results[\"#{secret_name}\"] = stringify_secret_value(secret_string)\n          end\n        rescue JSON::ParserError\n          results[\"#{secret_name}\"] = secret[\"SecretString\"]\n        end\n      end\n    end\n\n    def get_from_secrets_manager(secrets, account: nil)\n      args = [ \"aws\", \"secretsmanager\", \"batch-get-secret-value\", \"--secret-id-list\" ] + secrets.map(&:shellescape)\n      args += [ \"--profile\", account.shellescape ] if account\n      args += [ \"--output\", \"json\" ]\n      cmd = args.join(\" \")\n\n      `#{cmd}`.tap do |secrets|\n        raise RuntimeError, \"Could not read #{secrets} from AWS Secrets Manager\" unless $?.success?\n\n        secrets = JSON.parse(secrets)\n\n        return secrets[\"SecretValues\"] unless secrets[\"Errors\"].present?\n\n        raise RuntimeError, secrets[\"Errors\"].map { |error| \"#{error['SecretId']}: #{error['Message']}\" }.join(\" \")\n      end\n    end\n\n    def stringify_secret_value(value)\n      value.is_a?(String) ? value : JSON.dump(value)\n    end\n\n    def check_dependencies!\n      raise RuntimeError, \"AWS CLI is not installed\" unless cli_installed?\n    end\n\n    def cli_installed?","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/basecamp/kamal/blob/eee0083b38661c3707c6b6052cc89e85038a096c/lib/kamal/secrets/adapters/aws_secrets_manager.rb#L19-L55","documentation":"The AWS Secrets Manager adapter shells out to `aws secretsmanager batch-get-secret-value --secret-id-list ... [--profile X] --output json`; if that CLI process exits non-zero, Kamal raises RuntimeError. Note the message interpolates the raw CLI output, not the secret names, because the `tap do |secrets|` block variable shadows the secrets array — so the message shows whatever aws printed (often empty, since stderr is not captured).","triggerScenarios":"Expired SSO token or missing/invalid AWS credentials; wrong profile name passed via --account; awscli too old to have batch-get-secret-value; no network reachability to secretsmanager.<region>.amazonaws.com; the AWS_REGION/region not configured so the CLI errors out.","commonSituations":"CI job whose aws SSO session expired overnight; profile typo between deploy scripts; fresh machine with awscli v1 installed; corporate proxy or VPC without an secretsmanager endpoint.","solutions":["Reproduce manually with the exact command from the source: aws secretsmanager batch-get-secret-value --secret-id-list <name> --output json (add --profile if used) and read the stderr","Fix credentials: aws sso login (or refresh keys), and verify with aws sts get-caller-identity using the same profile","Set the region explicitly, e.g. export AWS_REGION=us-east-1, if the CLI has no default region","Upgrade to a current AWS CLI v2 (batch-get-secret-value is not in old v2 releases/v1)"],"exampleFix":"# before (failing)\nkamal secrets fetch -a aws_secrets_manager --account prod RAILS_MASTER_KEY\n\n# debug + fix (terminal)\naws sts get-caller-identity --profile prod      # verify creds\naws sso login --profile prod                     # refresh if expired\naws secretsmanager batch-get-secret-value --secret-id-list RAILS_MASTER_KEY --profile prod --output json","handlingStrategy":"try-catch","validationCode":"# Verify AWS auth/CLI health before running kamal\nsystem(\"aws --version > /dev/null 2>&1\") or abort \"aws CLI missing\"\nsystem(\"aws sts get-caller-identity #{ENV[\"AWS_PROFILE\"] ? \"--profile #{ENV[\"AWS_PROFILE\"]}\" : \"\"} > /dev/null\") or abort \"AWS credentials invalid/expired\"","typeGuard":null,"tryCatchPattern":"begin\n  results = adapter.fetch(secret_names, account: \"prod\")\nrescue RuntimeError => e\n  warn \"aws CLI failure — re-run manually: aws secretsmanager batch-get-secret-value --secret-id-list #{secret_names.join(' ')} --profile prod --output json\"\n  warn e.message\n  exit 1\nend","preventionTips":["Refresh SSO tokens before fetch jobs: aws sso login --profile <p> as a pipeline pre-step","Pin a modern awscli v2 in CI images; batch-get-secret-value needs a recent release","Set AWS_REGION explicitly in automation so the CLI never fails on missing region config"],"tags":["kamal","secrets","aws","cli","credentials","aws-cli"],"backgroundTag":"cloud-secret-fetch-failed","analyzedSha":"eee0083b38661c3707c6b6052cc89e85038a096c","analyzedAt":"2026-08-21T15:17:22.045Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}