# Fix AWS Parameter Store Error
Your application can't retrieve parameters from AWS Systems Manager Parameter Store. You're getting errors like "AccessDeniedException," "ParameterNotFound," or "ThrottlingException." Parameter Store is a simple but critical service for storing configuration data, secrets, and application settings, and when it fails, your application might not start or misconfigure itself.
This guide covers the common Parameter Store errors and how to fix them.
Diagnosis Commands
First, verify your identity:
aws sts get-caller-identityList parameters you have access to:
aws ssm describe-parameters \
--query 'Parameters[*].[Name,Type,Description,LastModifiedDate]'Try to get a specific parameter:
aws ssm get-parameter \
--name /my-app/database-url \
--query 'Parameter.[Name,Value,Type]'For SecureString parameters (encrypted):
aws ssm get-parameter \
--name /my-app/database-password \
--with-decryption \
--query 'Parameter.Value'Check parameter metadata:
aws ssm describe-parameters \
--filters "Name=Name,Values=/my-app/database-url" \
--query 'Parameters[*].[Name,Type,KeyId,Tier]'Check your IAM policies:
aws iam list-user-policies --user-name my-user
aws iam list-attached-user-policies --user-name my-userGet policy details:
aws iam get-user-policy \
--user-name my-user \
--policy-name SSMParameterPolicyUse policy simulator:
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:user/my-user \
--action-names ssm:GetParameter,ssm:GetParameters \
--resource-arns arn:aws:ssm:us-east-1:123456789012:parameter/my-app/*Check for throttling:
aws cloudwatch get-metric-statistics \
--namespace AWS/SSM \
--metric-name ThrottledRequests \
--dimensions Name=Operation,Value=GetParameter \
--start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
--period 60 \
--statistics SumCommon Causes and Solutions
Parameter Not Found
The parameter doesn't exist or the name is wrong:
aws ssm describe-parameters \
--filters "Name=Name,Values=/my-app/database-url"If empty, the parameter doesn't exist. Create it:
aws ssm put-parameter \
--name /my-app/database-url \
--value "jdbc:postgresql://mydb.example.com:5432/app" \
--type String \
--description "Database connection URL" \
--tier StandardCommon naming mistakes:
- Missing leading / (all names should start with / for hierarchical paths)
- Wrong case (Parameter Store is case-sensitive)
- Wrong path component
```bash # Bad: No leading slash aws ssm get-parameter --name my-app/database-url
# Good: With leading slash aws ssm get-parameter --name /my-app/database-url ```
List all parameters to find the correct name:
aws ssm describe-parameters \
--query 'Parameters[*].Name' \
--output text | tr '\t' '\n' | grep my-appAccess Denied
Missing IAM permissions to read parameters:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:GetParametersByPath",
"ssm:DescribeParameters"
],
"Resource": "arn:aws:ssm:us-east-1:123456789012:parameter/my-app/*"
}
]
}Apply the policy:
aws iam put-role-policy \
--role-name my-role \
--policy-name SSMParameterAccess \
--policy-document file://ssm-policy.jsonFor specific parameters:
{
"Resource": [
"arn:aws:ssm:us-east-1:123456789012:parameter/my-app/database-url",
"arn:aws:ssm:us-east-1:123456789012:parameter/my-app/api-key"
]
}SecureString Without KMS Permission
SecureString parameters use KMS for encryption:
aws ssm describe-parameters \
--filters "Name=Type,Values=SecureString" \
--query 'Parameters[*].[Name,KeyId]'If KeyId shows a specific key (not aws/ssm), you need KMS decrypt permission:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"kms:Decrypt"
],
"Resource": [
"arn:aws:ssm:us-east-1:123456789012:parameter/my-app/secure-*",
"arn:aws:kms:us-east-1:123456789012:key/my-key-id"
]
}
]
}For default encryption (alias/aws/ssm):
{
"Resource": "arn:aws:kms:us-east-1:123456789012:alias/aws/ssm"
}Permission Boundary Restriction
Permission boundaries limit maximum permissions:
aws iam get-role \
--role-name my-role \
--query 'Role.PermissionsBoundary'If set, the boundary must allow SSM actions:
aws iam get-policy-version \
--policy-arn arn:aws:iam::123456789012:policy/my-boundary \
--version-id v1 \
--query 'Document' \
--output text | jq '.Statement[] | select(.Action | contains("ssm"))'Parameter Version Issues
Parameters have versions. If you're accessing a deleted version:
aws ssm get-parameter \
--name /my-app/database-url \
--query 'Parameter.Version'Get parameter history:
aws ssm get-parameter-history \
--name /my-app/database-url \
--query 'Parameters[*].[Version,LastModifiedDate,Value]'Specify a version if needed:
aws ssm get-parameter \
--name /my-app/database-url \
--version 2Throttling Errors
Parameter Store has API rate limits. Standard tier: 40 transactions per second per region per account. Advanced tier: higher limits.
Check throttling metrics:
aws cloudwatch get-metric-statistics \
--namespace AWS/SSM \
--metric-name ThrottledRequests \
--start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
--period 60 \
--statistics Sum- 1.Reduce API calls by:
- 2.Using GetParameters for multiple parameters in one call:
aws ssm get-parameters \
--names "/my-app/database-url" "/my-app/api-key" "/my-app/config" \
--query 'Parameters[*].[Name,Value]'- 1.Using GetParametersByPath for hierarchical retrieval:
aws ssm get-parameters-by-path \
--path /my-app/ \
--recursive \
--with-decryption \
--query 'Parameters[*].[Name,Value]'- 1.Upgrade to Advanced tier for higher limits:
aws ssm put-parameter \
--name /my-app/config \
--value "config-value" \
--type String \
--tier Advanced \
--overwrite- 1.Implement caching in your application:
```python import boto3 from functools import lru_cache
ssm = boto3.client('ssm')
@lru_cache(maxsize=128) def get_cached_parameter(name, ttl=300): return ssm.get_parameter(Name=name, WithDecryption=True)['Parameter']['Value'] ```
Cross-Account Access
To access parameters in another account:
In Account B (parameter owner):
- 1.No direct sharing. Options:
- 2.Share via AWS Resource Access Manager (RAM) - not available for Parameter Store
- 3.Replicate parameters to Account A
- 4.Use Lambda in Account B to expose parameters
Alternative: Use Systems Manager Shared Parameters:
```bash # In Account B aws ssm put-parameter \ --name /shared/database-url \ --value "value" \ --type String
# Can't directly share, need alternative approaches ```
Workaround using Lambda:
```python # Lambda in Account B import boto3
def lambda_handler(event, context): ssm = boto3.client('ssm') return ssm.get_parameter(Name=event['parameter_name'], WithDecryption=True) ```
Invalid Parameter Value
Parameter value has format issues:
aws ssm put-parameter \
--name /my-app/invalid \
--value "value with special characters" \
--type StringListStringList values must be comma-separated without spaces:
```bash # Bad: Spaces around commas aws ssm put-parameter --name /my-app/list --value "a, b, c" --type StringList
# Good: No spaces aws ssm put-parameter --name /my-app/list --value "a,b,c" --type StringList ```
Parameter Deleted
Parameter was deleted but code still references it:
aws ssm describe-parameters \
--filters "Name=Name,Values=/my-app/deleted-param"If empty, recreate the parameter:
aws ssm put-parameter \
--name /my-app/deleted-param \
--value "new value" \
--type StringLabel Issues
Parameters can have labels pointing to specific versions:
aws ssm get-parameter \
--name /my-app/config:latest \
--query 'Parameter.[Value,Version]'Check labels:
aws ssm list-tags-for-resource \
--resource-type Parameter \
--resource-id /my-app/configWrong Region
Parameters are region-specific. Ensure you're using the correct region:
aws ssm describe-parameters \
--region us-east-1 \
--query 'Parameters[*].Name'Set region in your SDK:
```python import boto3
ssm = boto3.client('ssm', region_name='us-east-1') ```
Verification Steps
After fixing, verify parameter access:
aws ssm get-parameter \
--name /my-app/database-url \
--with-decryption \
--query 'Parameter.[Name,Type,Value]'Get all parameters under a path:
aws ssm get-parameters-by-path \
--path /my-app/ \
--recursive \
--with-decryption \
--query 'Parameters[*].[Name,Value]'Test multiple parameters:
aws ssm get-parameters \
--names "/my-app/database-url" "/my-app/api-key" \
--with-decryption \
--query '[Parameters[*].Name,InvalidParameters]'Create diagnostic script:
```bash #!/bin/bash PARAM_NAME="/my-app/database-url"
echo "Parameter Store Diagnostics" echo "==========================="
echo "1. Caller Identity:" aws sts get-caller-identity
echo "" echo "2. Parameter Exists:" aws ssm describe-parameters \ --filters "Name=Name,Values=$PARAM_NAME" \ --query 'Parameters[*].[Name,Type,Tier,KeyId,LastModifiedDate]'
echo "" echo "3. Parameter Value:" aws ssm get-parameter \ --name $PARAM_NAME \ --with-decryption \ --query 'Parameter.[Name,Value,Version,Type]' 2>&1
echo "" echo "4. IAM Policies for SSM:" aws iam list-role-policies \ --role-name $(aws sts get-caller-identity --query Arn --output text | cut -d'/' -f2) \ --query 'PolicyNames' 2>&1 || echo "Using user policies" aws iam list-user-policies \ --user-name $(aws sts get-caller-identity --query Arn --output text | cut -d'/' -f2) \ --query 'PolicyNames' 2>&1
echo "" echo "5. Policy Simulator Test:" aws iam simulate-principal-policy \ --policy-source-arn $(aws sts get-caller-identity --query Arn --output text) \ --action-names ssm:GetParameter \ --resource-arns arn:aws:ssm:*:*:parameter$PARAM_NAME \ --query 'EvaluationResults[*].[EvalActionName,EvalResourceName,EvalDecision]'
echo "" echo "6. Recent Throttling:" aws cloudwatch get-metric-statistics \ --namespace AWS/SSM \ --metric-name ThrottledRequests \ --start-time $(date -u -d '30 minutes ago' +%Y-%m-%dT%H:%M:%SZ) \ --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \ --period 60 \ --statistics Sum ```
Set up monitoring:
aws cloudwatch put-metric-alarm \
--alarm-name ssm-parameter-throttled \
--alarm-description "Parameter Store API throttled" \
--namespace AWS/SSM \
--metric-name ThrottledRequests \
--statistic Sum \
--period 60 \
--threshold 10 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 1 \
--alarm-actions arn:aws:sns:us-east-1:123456789012:alerts