# S3 CORS Configuration: Common Pitfalls That Cause Invalid JSON Errors in AWS SDK for JavaScript v3

> Learn common pitfalls causing invalid JSON errors with S3 CORS configuration in AWS SDK for JavaScript v3. Avoid mismatches with CORSRule and CORSConfiguration shapes.

- Repository: [Amazon Web Services/aws-sdk-js-v3](https://github.com/aws/aws-sdk-js-v3)
- Tags: how-to-guide
- Published: 2026-02-16

---

**The AWS SDK for JavaScript v3 expects a typed JavaScript object matching the `PutBucketCorsRequest` interface, not raw JSON, and "invalid JSON" errors typically indicate a mismatch between your object structure and the required `CORSRule`, `CORSConfiguration`, or `PutBucketCorsRequest` shapes defined in the SDK.**

When configuring Cross-Origin Resource Sharing (CORS) for Amazon S3 using the AWS SDK for JavaScript v3, the `PutBucketCorsCommand` does not accept a raw JSON payload. Instead, the SDK validates your input against TypeScript interfaces defined in [`clients/client-s3/src/models/models_0.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/models/models_0.ts) and serializes the object to XML before transmission. Understanding this serialization pipeline is critical to diagnosing cryptic "invalid JSON format" or "Invalid request payload" errors that surface during development.

## Why You Get "Invalid JSON" Errors When Configuring S3 CORS

The AWS SDK for JavaScript v3 translates your JavaScript object into an XML document that matches the S3 REST API specification for the `PUT ?cors` operation. Before any network request is dispatched, the SDK's protocol serializer (referenced in [`clients/client-s3/src/schemas/schemas_0.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/schemas/schemas_0.ts) at line 3187) validates the input against the operation schema. If your object lacks required fields, uses incorrect property names, or violates type constraints, the serializer throws an error that often manifests as "invalid JSON format" because the SDK treats the malformed object as unparsable input.

## Seven Common S3 CORS Configuration Mistakes

### Missing Required Fields on CORSRule

Every `CORSRule` must include the `AllowedMethods` and `AllowedOrigins` properties as arrays. In [`clients/client-s3/src/models/models_0.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/models/models_0.ts), the `CORSRule` interface explicitly marks these fields as required: `AllowedMethods: string[]; AllowedOrigins: string[];`. If either is undefined, the serializer cannot construct the XML elements and aborts with a payload error.

### Incorrect Property Casing

The SDK performs exact property name matching. Using lowercase `allowedMethods` or `allowedOrigins` instead of the PascalCase `AllowedMethods` and `AllowedOrigins` causes the SDK to ignore the keys, resulting in missing required values. Always use the exact interface keys: `AllowedMethods`, `AllowedOrigins`, `AllowedHeaders`, `ExposeHeaders`, `MaxAgeSeconds`, and `ID`.

### Scalars Instead of Arrays

Supplying a single string like `"GET"` instead of an array `["GET"]` breaks the serializer. The protocol implementation expects to iterate over these values to generate multiple XML elements (e.g., `<AllowedMethod>GET</AllowedMethod>`). Wrap single values in arrays: `AllowedMethods: ["GET"]`.

### Malformed JSON Syntax in Object Literals

JavaScript object literals are not JSON. Trailing commas after the last property or comments (`// ...`) inside object definitions create parse errors before the SDK ever sees the data. Remove trailing commas and use plain object literals without comments.

### Missing CORSConfiguration Wrapper

A frequent structural error is passing the array of rules directly instead of nesting it inside a `CORSConfiguration` object. The `PutBucketCorsRequest` shape requires this exact hierarchy: `{ Bucket: "...", CORSConfiguration: { CORSRules: [...] } }`. Providing `{ CORSRules: [...] }` at the top level leaves `CORSConfiguration` undefined, causing validation to fail.

### Incorrectly Typed MaxAgeSeconds

The `MaxAgeSeconds` field must be a number, not a string. Passing `"3000"` instead of `3000` results in invalid XML generation, as the serializer emits the string value verbatim where an integer is required by the S3 API schema.

### Exceeding Service Limits

While not strictly a JSON format error, exceeding the S3 limits of 100 CORS rules or a total configuration size greater than 64 KB can cause the SDK to reject the payload preemptively or the service to return errors that the SDK surfaces as client-side validation failures.

## How the SDK Serializes Your CORS Configuration

When you call `new PutBucketCorsCommand(input)`, the middleware stack performs three critical steps:

1. **Schema Validation**: The input is checked against the `PutBucketCors` operation schema in [`clients/client-s3/src/schemas/schemas_0.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/schemas/schemas_0.ts).
2. **XML Serialization**: The `s3` protocol serializer converts the JavaScript object to an XML document matching the S3 CORS API specification.
3. **Request Construction**: The generated XML is attached to the HTTP request body and sent to S3.

If the input object does not satisfy the TypeScript definitions, the serializer throws before any network call, surfacing as an "invalid JSON" error.

## Correct S3 CORS Configuration Examples

### Minimal Valid Configuration

This example matches the exact structure defined in [`clients/client-s3/src/models/models_0.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/models/models_0.ts):

```typescript
import { S3Client, PutBucketCorsCommand } from "@aws-sdk/client-s3";

const client = new S3Client({ region: "us-east-1" });

const corsConfig = {
  Bucket: "my-example-bucket",
  CORSConfiguration: {
    CORSRules: [
      {
        ID: "AllowGETFromAnyOrigin",
        AllowedMethods: ["GET"],
        AllowedOrigins: ["*"],
        AllowedHeaders: ["*"],
        ExposeHeaders: ["ETag"],
        MaxAgeSeconds: 3000,
      },
    ],
  },
};

await client.send(new PutBucketCorsCommand(corsConfig));

```

### Multiple Rules Configuration

When defining multiple origins or methods, ensure each rule maintains the required array structure:

```typescript
const multiRuleConfig = {
  Bucket: "my-example-bucket",
  CORSConfiguration: {
    CORSRules: [
      {
        ID: "ReadOnly",
        AllowedMethods: ["GET", "HEAD"],
        AllowedOrigins: ["https://example.com"],
        AllowedHeaders: ["*"],
        MaxAgeSeconds: 600,
      },
      {
        ID: "WriteOnly",
        AllowedMethods: ["PUT", "POST"],
        AllowedOrigins: ["https://api.example.com"],
        AllowedHeaders: ["Authorization", "Content-Type"],
        ExposeHeaders: ["ETag", "x-amz-request-id"],
        MaxAgeSeconds: 1200,
      },
    ],
  },
};

await client.send(new PutBucketCorsCommand(multiRuleConfig));

```

### Debugging with SDK Logging

To inspect the generated XML and verify your configuration reaches the serializer correctly, enable logging:

```typescript
import { S3Client, PutBucketCorsCommand } from "@aws-sdk/client-s3";

const client = new S3Client({ 
  region: "us-east-1", 
  logger: console 
});

await client.send(new PutBucketCorsCommand(corsConfig));

```

The console output will display the final XML payload, allowing you to verify that `AllowedMethod` and `AllowedOrigin` elements are correctly generated from your arrays.

## Summary

- **The AWS SDK for JavaScript v3 validates against TypeScript interfaces**, not JSON schema, when processing `PutBucketCorsCommand`.
- **Required fields are non-negotiable**: Every `CORSRule` must include `AllowedMethods` and `AllowedOrigins` as arrays.
- **Property names are case-sensitive**: Use `AllowedMethods`, not `allowedMethods`.
- **Structure matters**: Always wrap rules in `{ CORSConfiguration: { CORSRules: [...] } }`.
- **Types must match**: `MaxAgeSeconds` requires a number, not a string.
- **Limits apply**: Maximum 100 rules and 64 KB total configuration size.
- **Source authority**: The shapes are defined in [`clients/client-s3/src/models/models_0.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/models/models_0.ts) and serialized via [`clients/client-s3/src/schemas/schemas_0.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/schemas/schemas_0.ts).

## Frequently Asked Questions

### Does the AWS SDK for JavaScript v3 send JSON to S3 for CORS configuration?

No. The SDK accepts a JavaScript object and serializes it to XML according to the S3 REST API specification. The "invalid JSON" error message refers to the SDK's internal validation failure when your object does not match the required TypeScript interfaces, not to the wire format sent to S3.

### Why am I seeing "Invalid JSON format" when I haven't sent any JSON?

This error occurs during the SDK's client-side validation phase. When you instantiate `PutBucketCorsCommand`, the middleware validates your input object against the operation schema defined in [`clients/client-s3/src/schemas/schemas_0.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/schemas/schemas_0.ts). If the object structure deviates from the expected shape—such as missing required fields or incorrect nesting—the serializer reports the object as unparsable, often using "invalid JSON" as the error descriptor.

### What are the exact required fields for a CORSRule in the AWS SDK?

According to the `CORSRule` interface in [`clients/client-s3/src/models/models_0.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/models/models_0.ts), only `AllowedMethods` and `AllowedOrigins` are strictly required, both typed as `string[]`. All other fields—`ID`, `AllowedHeaders`, `ExposeHeaders`, and `MaxAgeSeconds`—are optional, though `MaxAgeSeconds` must be a `number` when provided.

### How can I verify my CORS configuration before sending it to S3?

Enable the SDK's built-in logger by passing `logger: console` to your `S3Client` constructor. This outputs the generated XML payload to your console, allowing you to verify that required elements like `<AllowedMethod>` and `<AllowedOrigin>` are present and correctly formatted before the HTTP request is dispatched to the S3 service.