Autoscaling Report: Production databases on Neon use 2.4x less compute and 50% less cost than if they were running on a provisioned platform.
/Object Storage/Troubleshooting

Storage troubleshooting

Common errors and how to fix them

Private Preview

This feature is in private preview: it's not ready for production use, and it may be briefly unavailable as we deploy updates. To get access, sign up here.

Authentication errors

403 InvalidAccessKeyId

The Access Key ID is wrong, missing, or the credential has been revoked.

Fix: Check that AWS_ACCESS_KEY_ID is set to the token_id from the credential response, not token_id_short. See Authentication for the correct field mapping. If you no longer have it, revoke the credential and create a new one.

403 SignatureDoesNotMatch

The Secret Access Key is wrong.

Fix: Check that AWS_SECRET_ACCESS_KEY is set to the s3_secret_access_key field from the credential response. This is the 64-character hex string, not the api_token. Both are returned only once at creation. If you no longer have the s3_secret_access_key, revoke the credential and create a new one.

403 AccessDenied: missing scope

The credential does not have the required scope for the operation.

Fix: Check which scopes the credential was created with:

  • storage:read allows GetObject, HeadObject, ListBuckets, and ListObjectsV2
  • storage:write allows all reads plus PutObject, DeleteObject, CreateBucket, and DeleteBucket

To add write access, create a new credential with storage:write. You can't add scopes to an existing credential.

403 AccessDenied: wrong branch

The credential was issued on a branch that is not an ancestor of the branch you are making requests against.

Fix: Use a credential issued on the target branch or one of its ancestor branches. See Authentication for how branch binding works.

SDK configuration errors

Requests go to AWS instead of Neon

If you forget to set the custom endpoint, the SDK will route requests to AWS S3 and fail with a credentials error or bucket-not-found.

Fix: Always set the endpoint (JavaScript) or endpoint_url (Python/CLI) to your branch storage host:

const client = new S3Client({
  endpoint: process.env.AWS_ENDPOINT_URL_S3,
  // ...
});

NoSuchBucketon every request

Without forcePathStyle: true, the SDK treats the bucket name as a subdomain instead of a path segment.

Fix: Add forcePathStyle: true to your S3Client configuration:

const client = new S3Client({
  forcePathStyle: true, // required for Neon Storage
  // ...
});

Without this, the AWS SDK for JavaScript uses virtual-hosted-style addressing (my-bucket.storage.example.com/key) which Neon Storage doesn't support.

SigV2 errors

If you see signature-related errors mentioning AWS2 or AWSAccessKeyId, your client is using the older AWS Signature Version 2.

Fix: Use AWS Signature Version 4 (SigV4). The AWS SDK v3 for JavaScript and boto3 use SigV4 by default. If you're using an older SDK or a custom HTTP client, update it or configure it to use SigV4 explicitly.

Access level errors

Anonymous GET returns403 AccessDenied

The bucket's access level is private (the default), which requires authentication for all reads.

Fix: If the bucket should allow public reads, set its access level to public_read using the Neon Console or API. See Access levels.

note

You cannot change access level via the S3 API. PutBucketAcl returns 501 Not Implemented.

S3 operation errors

501 Not Implemented

You are calling an S3 operation that Neon Storage does not support.

Common causes:

  • PutBucketAcl or PutBucketPolicy: use the Neon Console or API to set bucket access level instead
  • PutBucketNotificationConfiguration: event notifications are not supported
  • PutBucketLogging: server-side access logging is not supported

See S3 compatibility for the full list of unsupported operations.

Lifecycle rules not running

PutBucketLifecycle succeeds and the configuration is stored, but expiration and transition rules do not execute.

Status: Lifecycle enforcement isn't available in Private Preview. The API accepts and echoes the configuration so tools that read lifecycle rules will work, but the rules have no effect.

Connection and performance errors

503 Service Unavailable(SlowDown)

The request exceeded the per-IP or per-tenant rate limit. The S3 error code is SlowDown. This is a rate limit signal, not a server error. The storage service is healthy.

Fix: Implement exponential backoff and retry. Don't treat SlowDown as a fatal error. The response may include a Retry-After header indicating how long to wait. AWS SDKs handle this automatically when retry logic is enabled.

Large downloads timing out mid-stream

The connection drops during a large object download.

Fix: Use range requests to download large objects in chunks:

// Download in 10 MiB chunks
const chunkSize = 10 * 1024 * 1024;
let start = 0;

while (true) {
  const response = await client.send(new GetObjectCommand({
    Bucket: 'my-bucket',
    Key: 'large-file.zip',
    Range: `bytes=${start}-${start + chunkSize - 1}`,
  }));
  // process response.Body
  if (response.ContentRange?.endsWith(response.ContentLength?.toString() ?? '')) break;
  start += chunkSize;
}

Need help?

Join our Discord Server to ask questions or see what others are doing with Neon. For paid plan support options, see Support.

Was this page helpful?
Edit on GitHub