Skip to content

bug(aws-sqs): SQS emulator only accepts XML query protocol; AWS SDK v3 defaults to AwsJson1.0 #95

@tysmmsy

Description

@tysmmsy

Problem

The SQS emulator only accepts the legacy XML query protocol (form-encoded Action=…), but @aws-sdk/client-sqs defaults to the AWS JSON 1.0 protocol on every recent release. Pointing a current AWS SDK v3 SQS client at the emulator fails on the first call.

Reproduction

Against emulate@0.5.0, using @aws-sdk/client-sqs@3.1042.0:

import { SQSClient, ListQueuesCommand } from "@aws-sdk/client-sqs";

const sqs = new SQSClient({
  endpoint: "http://localhost:4007/sqs",
  region: "us-east-1",
  credentials: {
    accessKeyId: "AKIAIOSFODNN7EXAMPLE",
    secretAccessKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
  },
});

await sqs.send(new ListQueuesCommand({}));
SyntaxError: Unexpected token '<', "<?xml vers"... is not valid JSON

The same XML body is shown verbatim in client-iam and client-sts tests via the documented endpoint: "…/sts" / …/iam" workaround, but those services do work because their SDK clients still speak the query protocol. SQS does not.

Wire-level trace

Captured via a custom NodeHttpHandler to see exactly what crosses the socket.

What the SDK sends:

Method POST
URL http://localhost:4007/sqs/
Content-Type application/x-amz-json-1.0
X-Amz-Target AmazonSQS.ListQueues
Body {}

What the emulator returns:

Status 400
Content-Type application/xml
Body see below
<?xml version="1.0" encoding="UTF-8"?>
<ErrorResponse>
  <Error>
    <Code>InvalidAction</Code>
    <Message>The action  is not valid for this endpoint.</Message>
  </Error>
  <RequestId>…</RequestId>
</ErrorResponse>

The emulator parses the request as XML query, finds no Action= form parameter, and returns InvalidAction in XML. The SDK then runs the XML body through its JSON deserializer and surfaces the misleading Unexpected token '<' SyntaxError, which gives no hint that protocol negotiation is the underlying problem.

Root cause

AWS migrated SQS to AwsJson1.0 in 2023; @aws-sdk/client-sqs switched its default protocol to JSON shortly after, and every recent SDK lockfile pulls the JSON-by-default version. The emulator's packages/@emulators/aws/src/routes/sqs.ts only registers handlers under POST /sqs/ that read the form-encoded Action parameter, so any JSON-RPC request lands on the same route, fails the action-name check, and gets the XML error.

AWS announcement (CBOR / AwsJson1.0 for SQS): https://aws.amazon.com/blogs/developer/announcing-cbor-support-and-other-improvements-for-amazon-sqs/

Suggested fixes

Listed roughly in increasing scope:

  1. Dispatch on protocol headers in the SQS route. When Content-Type: application/x-amz-json-1.0 and X-Amz-Target: AmazonSQS.<Action> are present, parse the JSON body and respond with application/x-amz-json-1.0. Keep the existing XML query handler as a fallback (X-Amz-Query-Mode: true or no JSON headers). Smallest behavioral surface, most compatible with current SDK versions.
  2. Implement the JSON protocol path and treat XML query as the fallback. Mirrors the real AWS migration and avoids the SDK-version-pinning workaround that the README would otherwise need to document.
  3. At minimum, document the limitation. README currently doesn't mention that the SQS emulator requires the XML query protocol. A note pointing users to either pin @aws-sdk/client-sqs to a pre-JSON release or hit the endpoint via fetch/curl would at least save people from the cryptic Unexpected token '<' chase.

Happy to send a PR for (1) — that path is contained inside packages/@emulators/aws/src/routes/sqs.ts and a small request-shape adapter — once the maintainers confirm the direction.

Environment

  • emulate: 0.5.0
  • @aws-sdk/client-sqs: 3.1042.0
  • @smithy/node-http-handler: 4.6.1 (used to capture wire-level traffic)
  • Node.js: 24
  • OS: macOS 15

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions