jestjs/jest · error · Error

Expected is not a string

Error message

Expected is not a string

What it means

stringContaining / stringNotContaining build a StringContaining matcher whose constructor requires the sample to pass isA('String', sample). Anything that is not a string (number, object, undefined) throws an Error at construction time. This is a strict type guard so the substring `.includes()` call later is always valid.

Solutions

  1. Pass a plain string substring: `expect.stringContaining('hello')`.
  2. If you want regex matching, use `expect.stringMatching(/pattern/)` instead.
  3. Coerce or default the input: `expect.stringContaining(String(value ?? ''))` when the source may be missing.

Example fix

// before
expect(msg).toEqual(expect.stringContaining(/hello/)); // RegExp, not a string

// after
expect(msg).toEqual(expect.stringContaining('hello'));
// or for regex:
expect(msg).toEqual(expect.stringMatching(/hello/));
Defensive patterns

Strategy: type-guard

Validate before calling

function stringContainingSafe(sample) {
  if (typeof sample !== 'string') {
    throw new TypeError('stringContaining requires a string');
  }
  return expect.stringContaining(sample);
}

Type guard

function isString(v: unknown): v is string {
  return typeof v === 'string';
}

const m = isString(sample) ? expect.stringContaining(sample) : expect.anything();

Prevention

When it happens

Trigger: Calling `expect.stringContaining(value)` with a non-string value: a number, an object, a RegExp, or undefined. The error is thrown immediately when the matcher is constructed (before any assertion runs).

Common situations: Passing a RegExp where a substring was intended (use stringMatching for regex); passing a number that should have been a string; passing undefined from an optional field without a default.

Related errors


AI-assisted analysis of jestjs/jest@8e6d128e4a (2026-08-10). Data as JSON: /api/errors/2ac37afb6a23af58. Report an issue: GitHub.

Appendix: source

Thrown at packages/expect/src/asymmetricMatchers.ts:303

      }
    }

    return this.inverse ? !result : result;
  }

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

  override getExpectedType() {
    return 'object';
  }
}

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: unknown) {
    const result = isA<string>('String', other) && other.includes(this.sample);

    return this.inverse ? !result : result;
  }

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

  override getExpectedType() {
    return 'string';
  }
}

View on GitHub (pinned to 8e6d128e4a)