denoland/deno · error · TypeError

Expected the second argument to assertSnapshot() to be an op

Error message

Expected the second argument to assertSnapshot() to be an options object or a message string

What it means

Thrown by assertSnapshot() (cli/js/40_test_snapshot.js), the implementation behind t.assertSnapshot() in Deno tests. Besides the value under test, the call accepts either an options object ({ name, serializer, msg, ... }) or a plain string used as the failure message. Anything else as that argument is a TypeError.

Source

Thrown at cli/js/40_test_snapshot.js:319

}

function getErrorMessage(message, options) {
  return typeof options.msg === "string" ? options.msg : message;
}

/**
 * Implementation of `Deno.TestContext.assertSnapshot()`. `tContext` is the
 * test context object the method was called on.
 */
export function assertSnapshot(
  tContext,
  actual,
  options = { __proto__: null },
) {
  if (typeof options === "string") {
    options = { __proto__: null, msg: options };
  } else if (typeof options !== "object" || options === null) {
    throw new TypeError(
      "Expected the second argument to assertSnapshot() to be an options object or a message string",
    );
  }

  const context = getSnapshotContext(options);
  const testName = options.name ?? getFullTestName(tContext);
  const count = (MapPrototypeGet(context.counts, testName) ?? 0) + 1;
  MapPrototypeSet(context.counts, testName, count);
  const name = `${testName} ${count}`;

  if (!ArrayPrototypeIncludes(context.updateQueue, name)) {
    ArrayPrototypePush(context.updateQueue, name);
  }

  const serializer = options.serializer ?? serialize;
  const actualSnapshot = serializer(actual);
  if (typeof actualSnapshot !== "string") {
    throw new TypeError("Snapshot serializer must return a string");

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Pass an options object: t.assertSnapshot(value, { msg: "context" }) or t.assertSnapshot(value, { name: "my snapshot", serializer })
  2. Or pass the message directly as a string: t.assertSnapshot(value, "my message")
  3. If options come from a variable, default it: opts ?? {}

Example fix

// before
await t.assertSnapshot(result, true);

// after
await t.assertSnapshot(result, { msg: "rendered output" });
Defensive patterns

Strategy: type-guard

Validate before calling

function normalizeSnapshotOptions(arg) {
  if (typeof arg === "string") return { msg: arg };
  if (typeof arg === "object" && arg !== null) return arg;
  return {}; // or throw your own clearer error before calling the API
}

Type guard

/** @param {unknown} arg */
function isSnapshotOptionsOrMessage(arg) {
  return typeof arg === "string" ||
    (typeof arg === "object" && arg !== null);
}

Prevention

When it happens

Trigger: Calling t.assertSnapshot(value, opts) where opts is a boolean, number, symbol, or a non-object non-string — e.g. passing a message as a template-literal coercion attempt (true), passing options through a variable that is undefined-adjacent (e.g. a misnamed flag), or passing an array where the string|object union is expected (arrays pass the object check and are treated as an options object).

Common situations: Refactoring from assertEquals(value, expected, "msg") and passing a non-string third-arg habit into assertSnapshot; building options conditionally and letting a falsy sentinel (false/0) leak through; API drift from other snapshot libs whose signature is (value, nameStringOrObject).

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/385d1da86fd18471. Report an issue: GitHub.