Skip to content

Errors from different realms are not preserved #306

@anthonyting

Description

@anthonyting

Since we use instanceof Error checks in our code, if an Error does not come from the same realm (e.g. a separate vm context or a worker), then it will fail the check and pass a generic error.

We should probably use an isErrorLike function or something instead of checking instanceof, and also sweep the codebase for other uses of instanceof to make sure it will work fine with different realms.

Example:

import {
  DurableContext,
  withDurableExecution,
} from "@aws/durable-execution-sdk-js";
import { ExampleConfig } from "../../../types";
import * as vm from "vm";

export const config: ExampleConfig = {
  name: "Cross Realm Handler Error",
  description:
    "Demonstrates how errors thrown from different Node.js execution realms are captured and structured in results",
};

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    await context.step(
      async () => {
        // Create a new V8 context (different realm) and throw an error from it
        const vmContext = vm.createContext();

        // Execute code in the different realm that throws an error
        const code = `
      throw new Error("Error from different Node.js realm");
    `;

        // This will throw an error from a different V8 context/realm
        vm.runInContext(code, vmContext);
      },
      {
        retryStrategy: (error, attemptCount) => {
          if (error.message.includes("realm")) {
            return {
              shouldRetry: false,
            };
          }
          return {
            shouldRetry: attemptCount < 3,
          };
        },
      },
    );
  },
);
import { handler } from "./cross-realm-error";
import { createTests } from "../../../utils/test-helper";
import { ExecutionStatus } from "@aws/durable-execution-sdk-js-testing";

createTests({
  name: "cross-realm-error test",
  functionName: "cross-realm-error",
  handler,
  tests: (runner) => {
    it("should handle cross-realm errors gracefully and capture error details", async () => {
      const result = await runner.run({
        payload: { test: "cross-realm-error-case" },
      });

      // Check that error was captured in the result
      const error = result.getError();
      expect(error).toEqual({
        errorMessage: "Error from different Node.js realm",
        errorType: "StepError",
        stackTrace: undefined,
      });

      expect(result.getOperations()).toHaveLength(1);
      expect(runner.getOperationByIndex(0).getStepDetails()?.attempt).toBe(1);

      expect(result.getStatus()).toBe(ExecutionStatus.FAILED);
    });
  },
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinglanguage-sdkIssue relates to the Language SDK

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions