awslabs/llrt · error · Error

Expected is not a string

Error message

Expected is not a string

What it means

StringContaining is an asymmetric matcher that checks whether another string includes the given sample substring. The constructor validates that the sample is actually a string using isA("String", sample) and throws this plain Error if not, so malformed matchers fail fast instead of silently never matching. It mirrors Jest's own validation for expect.stringContaining.

Solutions

  1. Convert the sample to a string before passing it, e.g. expect.stringContaining(String(value)).
  2. Verify the variable actually holds a string; fix the source of the non-string value (often an API response field or undefined variable).
  3. Use expect.any(String) instead if you only care that the value is a string.
  4. Use expect.arrayContaining/objectContaining if you meant to match a non-string structure.

Example fix

// before
expect(log).toEqual(expect.stringContaining(404));
// after
expect(log).toEqual(expect.stringContaining(String(404)));
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof sample !== 'string') throw new TypeError('stringContaining sample must be a string');

Type guard

const isStr = (v: unknown): v is string => typeof v === 'string';

Try / catch

try { expect(x).toEqual(expect.stringContaining(s)); } catch (e) { if (!(e instanceof Error) || !/Expected is not a string/.test(e.message)) throw e; /* handle bad sample */ }

Prevention

When it happens

Trigger: Calling expect.stringContaining(x) (or expect.not.stringContaining(x)) where x is not a string — e.g. a number, null, undefined, or an object.

Common situations: Passing a number that looks like text (stringContaining(123)), passing a variable that is undefined due to a typo or failed lookup, or copying matchers between expect().toContain and expect().toStrictEqual where argument types differ.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of awslabs/llrt@742fc00b82 (2026-09-12). Data as JSON: /api/errors/fb7acd81127ff196. Report an issue: GitHub.

Appendix: source

Thrown at llrt_core/src/modules/js/@llrt/expect/jest-asymmetric-matchers.ts:83

  abstract asymmetricMatch(other: unknown): boolean;
  abstract toString(): string;
  getExpectedType?(): string;
  toAsymmetricMatcher?(): string;

  // implement custom chai/loupe inspect for better AssertionError.message formatting
  // https://github.com/chaijs/loupe/blob/9b8a6deabcd50adc056a64fb705896194710c5c6/src/index.ts#L29
  [Symbol.for("chai/inspect")](options: { depth: number; truncate: number }) {
    // minimal pretty-format with simple manual truncation
    const result = stringify(this, options.depth, { min: true });
    if (result.length <= options.truncate) return result;
    return `${this.toString()}{…}`;
  }
}

export class StringContaining extends AsymmetricMatcher<string> {
  constructor(sample: string, inverse = false) {
    if (!isA("String", sample)) throw new Error("Expected is not a string");

    super(sample, inverse);
  }

  asymmetricMatch(other: string) {
    const result = isA("String", other) && other.includes(this.sample);

    return this.inverse ? !result : result;
  }

  toString() {
    return `String${this.inverse ? "Not" : ""}Containing`;
  }

  getExpectedType() {
    return "string";
  }
}

View on GitHub (pinned to 742fc00b82)