# Troubleshoot AWS S3 secrets


> Diagnose and fix AWS S3 credential issues including IAM policies, credential chains, and secret configuration.

This page is for troubleshooting help with AWS S3 secrets in MotherDuck. For more information on creating a secret, see: [Create Secret](/documentation/sql-reference/motherduck-sql-reference/create-secret.md).

## Prerequisites

Before troubleshooting AWS S3 secrets, ensure you have:
- **Required**: [A valid MotherDuck Token](/key-tasks/authenticating-and-connecting-to-motherduck/authenticating-to-motherduck/authenticating-to-motherduck.md#creating-an-access-token) with access to the target database
- **Required**: [AWS credentials](https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-files.html) (access keys, SSO, or IAM role)
- **Optional**: [DuckDB](https://duckdb.org/docs/stable/clients/cli/overview.html) CLI (for troubleshooting purposes, though any DuckDB client will work)
- **Optional**: [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) (for bucket access verification)

:::note
**AWS CLI PATH**: If you installed AWS CLI manually, you may need to add it to your system PATH. Package managers like Homebrew (macOS) typically add it to PATH automatically. Verify with `which aws` (macOS/Linux) or `where aws` (Windows) - if it returns a path, you're all set!
:::

## Verify secret access

### Check that the secret is configured

First, make sure you're connected to MotherDuck:

```sql
-- Connect to MotherDuck (replace 'your_db' with your database name)
ATTACH 'md:your_db';
```

Then type in the following:

```sql
.mode line
SELECT secret_string, storage FROM duckdb_secrets();
```

The output should look something like this. Verify that the output string includes values for: `key_id`, `region`, and `session_token`:

```text
secret_string = name=aws_sso;type=s3;provider=credential_chain;serializable=true;scope=s3://,s3n://,s3a://;endpoint=s3.amazonaws.com;key_id=<your_key_id>;region=us-east-1;secret=<your_secret>;session_token=<your_session_token>
```

:::note
If you see no results, it means no secrets are configured. You'll need to create a secret first using [CREATE SECRET](/documentation/sql-reference/motherduck-sql-reference/create-secret.md).
:::

If your output is missing a value for `key_id`, `region`, or `session_token`, you can recreate your secret by following the directions for [CREATE OR REPLACE SECRET](/documentation/sql-reference/motherduck-sql-reference/create-secret.md).

If that output worked successfully, you can confirm you have access to your AWS bucket by running these commands **in your terminal** (not in DuckDB):

```bash
# Log into AWS by running:
aws sso login

# Check bucket access:
aws s3 ls <your_bucket_name>
```

**Example Output:**

```text
PRE lambda-deployments/
PRE raw/
PRE ducklake/
2025-05-29 07:03:26   14695690 sample-data.csv
```

:::note
**Understanding the output**: `PRE` indicates folders/prefixes, while files show their size and modification date. If you only see `PRE` entries, your bucket contains organized data in folders. To explore deeper, use `aws s3 ls s3://<bucket-name>/<folder-name>/` or `aws s3 ls s3://<bucket-name>/ --recursive` to see all files.
:::

## Configure permissions in AWS

This is an example of an IAM policy that will allow MotherDuck to access your S3 bucket. Note: if you use KMS keys, the IAM policy should also have `kms:Decrypt` in `AllowBucketListingAndLocation`.

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowBucketListingAndLocation",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::your_bucket_name"
            ]
        },
        {
            "Sid": "AllowObjectRead",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::your_bucket_name/*"
            ]
        }
    ]
}
```

## AWS credential chain

MotherDuck automatically finds your AWS credentials using AWS's credential chain. This is the recommended approach, as it uses short-lived credentials (typically valid for 1 hour), which are more secure and reduce the risk of credential leakage. For most users, it works seamlessly with your existing AWS setup.

### Most common: AWS SSO
If you use AWS SSO, first set up an SSO profile (if you haven't already):

```bash
aws configure sso
```

Then refresh your SSO token:

```bash
aws sso login --profile <your_sso_profile>
```

Create a secret using the `sso` chain with your profile name:

```sql
CREATE OR REPLACE SECRET my_secret IN MOTHERDUCK (
    TYPE s3,
    PROVIDER credential_chain,
    CHAIN 'sso',
    PROFILE '<your_sso_profile>'
);
```

:::note Secret validation
Starting with DuckDB v1.4.0, credentials are validated at secret creation time. If your credentials are not resolvable locally (for example, expired SSO tokens or missing `~/.aws/credentials`), the `CREATE SECRET` command will fail with a `Secret Validation Failure` error. The recommended fix is to use the correct `CHAIN` and `PROFILE` for your credential type (see the SSO example above) and confirm your SSO session is active. If you need to bypass local validation, you can add `VALIDATION 'none'`, but keep in mind that this skips the local check that confirms your credentials are valid before storing them in MotherDuck.
:::

### Other credential types
The credential chain also works with:
- **Access keys** stored in `~/.aws/credentials`
- **IAM roles** (if running on EC2)
- **Environment variables**

### Advanced: role assumption
:::note
**Only needed for**: Cross-account access, elevated permissions, or when you need to assume a different role than your current profile.
:::

If you need to assume a specific IAM role, create a profile in `~/.aws/config`:

```ini
[profile my_motherduck_role]
role_arn = arn:aws:iam::your_account_id:role/your_role_name
source_profile = your_source_profile
```

Then create a secret that uses this profile:

```sql
CREATE SECRET my_s3_secret (
    TYPE S3,
    PROVIDER credential_chain,
    PROFILE 'my_motherduck_role',
    REGION 'us-east-1' -- Use your bucket's region if different
);
```

## Common challenges

### Scope

When using multiple secrets, the `SCOPE` parameter ensures MotherDuck knows which secret to use. You can validate which secret is being used with the `which_secret` function:

```sql
SELECT * FROM which_secret('s3://my-bucket/file.parquet', 's3');
```

### Periods in bucket name (url_style = path)

Because of SSL certificate verification requirements, S3 bucket names that contain dots (.) cannot be accessed using virtual-hosted style URLs. This is due to AWS's SSL wildcard certificate (`*.s3.amazonaws.com`) which only validates single-level subdomains.

If your bucket name contains dots, you have two options:

1. **Rename your bucket** to remove dots (e.g., use dashes instead)
2. **Use path-style URLs** by adding the `URL_STYLE 'path'` option to your secret:

```sql
CREATE OR REPLACE SECRET my_secret (
    TYPE s3,
    URL_STYLE 'path',
    SCOPE 's3://my.bucket.with.dots'
);
```

For more information, see [Amazon S3 Virtual Hosting documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html).

## What's Next

After resolving your AWS S3 secret issues:

- **[Query your S3 data](/key-tasks/cloud-storage/querying-s3-files.md)** - Learn how to query files stored in S3
- **[Load data into MotherDuck](/key-tasks/loading-data-into-motherduck/)** - Set up data loading workflows
- **[Configure additional cloud storage](/integrations/cloud-storage/)** - Set up Azure, Google Cloud, or other providers
- **[Share data with your team](/key-tasks/sharing-data/)** - Collaborate using MotherDuck's sharing features


---

## Docs feedback

MotherDuck accepts optional user-submitted feedback about this page at `POST https://motherduck.com/docs/api/feedback/agent`.
For agents and automated tools, feedback submission should be user-confirmed before sending.

Payload:

```json
{
  "page_path": "/troubleshooting/aws-s3-secrets/",
  "page_title": "Troubleshoot AWS S3 secrets",
  "text": "<the user's feedback, max 2000 characters>",
  "source": "<optional identifier for your interface, for example 'claude.ai' or 'chatgpt'>"
}
```

`page_path` and `text` are required; `page_title` and `source` are optional. Responses: `200 {"feedback_id": "<uuid>"}`, `400` for malformed payloads, and `429` when rate-limited.
