basecamp/kamal · error · RuntimeError
#{error['SecretId']}: #{error['Message']}
Error message
#{error['SecretId']}: #{error['Message']} What it means
batch-get-secret-value can return HTTP 200 while still reporting per-secret failures in its Errors array; this RuntimeError surfaces each one as "<SecretId>: <Message>" joined by spaces. The aws CLI exited successfully but AWS refused or could not find at least one requested secret.
Source
Thrown at lib/kamal/secrets/adapters/aws_secrets_manager.rb:43
results["#{secret_name}"] = secret["SecretString"]
end
end
end
def get_from_secrets_manager(secrets, account: nil)
args = [ "aws", "secretsmanager", "batch-get-secret-value", "--secret-id-list" ] + secrets.map(&:shellescape)
args += [ "--profile", account.shellescape ] if account
args += [ "--output", "json" ]
cmd = args.join(" ")
`#{cmd}`.tap do |secrets|
raise RuntimeError, "Could not read #{secrets} from AWS Secrets Manager" unless $?.success?
secrets = JSON.parse(secrets)
return secrets["SecretValues"] unless secrets["Errors"].present?
raise RuntimeError, secrets["Errors"].map { |error| "#{error['SecretId']}: #{error['Message']}" }.join(" ")
end
end
def stringify_secret_value(value)
value.is_a?(String) ? value : JSON.dump(value)
end
def check_dependencies!
raise RuntimeError, "AWS CLI is not installed" unless cli_installed?
end
def cli_installed?
`aws --version 2> /dev/null`
$?.success?
end
end
View on GitHub (pinned to eee0083b38)
Solutions
- Verify the secret exists in the right account/region: aws secretsmanager describe-secret --secret-id <SecretId from the message> --profile <account>
- Add the missing IAM permission (secretsmanager:GetSecretValue, secretsmanager:DescribeSecret) for the secret's ARN to the principal in use
- Fix the secret name in the kamal secrets fetch arguments to match the full name in AWS
- Point at the correct region/profile (export AWS_REGION=... or pass --account matching an aws profile configured for that account)
Example fix
# error: myapp/RAILS_MASTER_KEY: User is not authorized...
# fix (IAM policy for the CI user/role)
{
"Effect": "Allow",
"Action": ["secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret"],
"Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:myapp/*"
}
# then retry
kamal secrets fetch -a aws_secrets_manager --account prod RAILS_MASTER_KEY Defensive patterns
Strategy: try-catch
Validate before calling
# Pre-check each secret exists and is readable before the batch fetch
secret_names.each do |name|
ok = system("aws secretsmanager describe-secret --secret-id #{name.shellescape} #{account ? "--profile #{account.shellescape}" : ""} > /dev/null 2>&1")
warn "warning: #{name} not visible to this credentials/region" unless ok
end Try / catch
begin
secrets = adapter.fetch(secret_names, account: account)
rescue RuntimeError => e
# e.message is "SecretId: AWS message" pairs — surface them per-secret
e.message.split(/ (?=\S+: )/).each { |pair| warn "AWS secretsmanager: #{pair}" }
raise
end Prevention
- Scope IAM to secretsmanager:GetSecretValue+DescribeSecret on the exact secret ARN pattern (e.g. arn:...:secret:myapp/*) and test with an deny-simulated policy
- Keep the AWS region in deploy scripts and secret naming in sync (myapp/<env>/... convention)
- Run the describe-secret pre-check above in CI to catch typos before the deploy needs them
When it happens
Trigger: ResourceNotFoundException for a secret id that does not exist in the configured account+region; AccessDeniedException when the IAM principal lacks secretsmanager:GetSecretValue/DescribeSecret; InvalidRequestException for malformed ids; secret exists but only in another region or another profile's account.
Common situations: Secret name typo or missing environment prefix (e.g. myapp/staging vs myapp/production); IAM policy scoped to specific secret ARNs that omit the requested one; default region pointing at us-east-1 while secrets live in eu-west-1; using the wrong --account profile.
Related errors
- Could not read #{item_name} from Google Secret Manager
- Could not read #{secrets} from AWS Secrets Manager
- AWS CLI is not installed
- Secret '#{key}' not found in #{secrets_files.join(", ")}
- Secret '#{key}' not found, no secret files (#{secrets_filena
AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21).
Data as JSON: /api/errors/b0f795dbf049ca54.
Report an issue: GitHub.