Skip to main content

Compilation errors

The most common TypeScript compilation error when working with this SDK looks like:
error TS2345: Argument of type 'X' is not assignable to parameter of type 'Y'.
  The types of 'Z' are incompatible between these types.
    ... many lines of tracing ...
      'A' is assignable to the constraint of type 'B', but 'B' could be instantiated
      with a different subtype of constraint 'C'.
This happens when different @aws-sdk/client-* packages in the same project depend on different versions of @smithy/types or @aws-sdk/types. Node’s module resolution can end up with multiple copies at different versions. Fix: pin all @aws-sdk/client-* packages to the same version range.
package.json
{
  "dependencies": {
    "@aws-sdk/client-s3": "<=3.800.0",
    "@aws-sdk/client-dynamodb": "<=3.800.0",
    "@aws-sdk/client-lambda": "<=3.800.0"
  }
}
The <= prefix installs the greatest version at or below the given value. Not every minor version number is published for every package, since the monorepo version increments daily but packages are only published when they change.

Runtime errors before a request is sent

Because the SDK provides a TypeScript API, it does not runtime-typecheck every value (that would increase bundle size). If you pass an incorrect type, the error may be thrown before any network request is made.
import { S3 } from "@aws-sdk/client-s3";

const s3 = new S3();

await s3.getObject({
  Bucket: "my-bucket",
  Key: 5 as any, // should be a string — throws before the request is sent
  // TypeError: labelValue.split is not a function
});
When you encounter an error like this, check the API documentation or TypeScript declarations for the correct input types.

Service errors: modeled vs unmodeled

Non-2xx responses from AWS services are thrown as JavaScript Error objects. The SDK distinguishes two kinds:
  • Modeled errors are declared in the service model. For example, NoSuchBucket is a modeled error for S3 — it appears in the list of named exceptions for each operation in the API reference.
  • Unmodeled errors are not in the service model. They may come from routing layers, load balancers, or security infrastructure in front of the service, or simply be incompletely modeled by the service team.
Both types extend the per-service base exception class (for example, S3ServiceException for S3, LambdaServiceException for Lambda). Unmodeled errors are returned as an instance of this base class.

Handling service errors

import { Lambda } from "@aws-sdk/client-lambda";
import {
  CodeStorageExceededException,
  LambdaServiceException,
  TooManyRequestsException,
} from "@aws-sdk/client-lambda";

const lambda = new Lambda({});

// Helper to narrow unknown to the service base error type
function isSdkServiceError(e: unknown): e is LambdaServiceException {
  return !!(e as LambdaServiceException)?.$metadata;
}

try {
  await lambda.createFunction({ /* ... */ });
} catch (e: unknown) {
  if (isSdkServiceError(e)) {
    // Match by error name
    switch (e.name) {
      case CodeStorageExceededException.name:
        // handle storage exceeded
        break;
      case TooManyRequestsException.name:
        // handle rate limiting
        break;
      default:
        // all other Lambda service errors
    }

    // Or match by HTTP status code
    switch (e.$metadata.httpStatusCode) {
      case 429:
        // throttled
        break;
      case 403:
        // forbidden
        break;
      case 404:
        // not found
        break;
    }

    // Access raw HTTP response headers
    const headerValue = e.$response?.headers["header-name"];
  }
  throw e;
}
Although instanceof checks can be unreliable when NPM installs multiple copies of a package, the SDK’s base ServiceException type overrides Symbol.hasInstance, so instanceof works correctly across package copies.

The $metadata object

Every service exception includes a $metadata field:
FieldTypeDescription
httpStatusCodenumberHTTP status code from the response
requestIdstringUnique identifier for the request, useful for AWS support
attemptsnumberNumber of request attempts made (including retries)
totalRetryDelaynumberTotal milliseconds spent waiting between retries

Using instanceof with specific error classes

import { S3ServiceException, NoSuchBucket } from "@aws-sdk/client-s3";

try {
  await s3.getObject({ Bucket: "my-bucket", Key: "my-key" });
} catch (err) {
  if (err instanceof NoSuchBucket) {
    // handle missing bucket specifically
  } else if (err instanceof S3ServiceException) {
    // handle any other S3 service error
    console.log(err.name, err.message, err.$metadata.httpStatusCode);
  }
  throw err;
}

Parsing errors from service responses

If the SDK fails to parse an error response (for example, because a front-end layer returns plaintext when the service model expects JSON), the error message will include:
Deserialization error: to see the raw response, inspect the hidden field {error}.$response on this object.
An additional untyped field $responseBodyText will contain the raw response body. It is not logged automatically to avoid accidental leaking of sensitive data.
import { S3 } from "@aws-sdk/client-s3";

const client = new S3();

try {
  await client.listBuckets();
} catch (e: any) {
  if (e.$responseBodyText) {
    console.debug(e.$responseBodyText);
  }
}

Build docs developers (and LLMs) love