{"id":"415a72f625cb13ea","repo":"vitest-dev/vitest","slug":"expected-is-not-a-string-or-a-regexp","errorCode":null,"errorMessage":"Expected is not a String or a RegExp","messagePattern":"Expected is not a String or a RegExp","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/expect/src/jest-asymmetric-matchers.ts","lineNumber":320,"sourceCode":"      return 'object'\n    }\n\n    if (this.sample === Boolean) {\n      return 'boolean'\n    }\n\n    return this.fnNameFor(this.sample)\n  }\n\n  toAsymmetricMatcher() {\n    return `Any<${this.fnNameFor(this.sample)}>`\n  }\n}\n\nexport class StringMatching extends AsymmetricMatcher<RegExp> {\n  constructor(sample: string | RegExp, inverse = false) {\n    if (!isA('String', sample) && !isA('RegExp', sample)) {\n      throw new Error('Expected is not a String or a RegExp')\n    }\n\n    super(new RegExp(sample), inverse)\n  }\n\n  asymmetricMatch(other: string): boolean {\n    const result = isA('String', other) && this.sample.test(other)\n\n    return this.inverse ? !result : result\n  }\n\n  toString() {\n    return `String${this.inverse ? 'Not' : ''}Matching`\n  }\n\n  getExpectedType() {\n    return 'string'\n  }","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/expect/src/jest-asymmetric-matchers.ts#L302-L338","documentation":"Thrown by the StringMatching asymmetric matcher constructor when the sample is neither a string nor a RegExp (checked via isA('String') and isA('RegExp')). StringMatching compiles the sample into a RegExp to test substring/pattern inclusion.","triggerScenarios":"Constructing expect.stringMatching(value) where value is a number, object, null, etc. Neither guard passes so the constructor throws before compiling.","commonSituations":"Passing a RegExp flags object, a number, or a non-string variable; confusing stringMatching with a generic matcher; a refactor that changed the sample type.","solutions":["Pass a string pattern or a RegExp: expect.stringMatching(/^foo/) or expect.stringMatching('foo').","For object shape checks use objectContaining; for arrays use arrayContaining.","Validate the variable is string|RegExp before constructing the matcher."],"exampleFix":"// before\nexpect(msg).toEqual(expect.stringMatching(123))\n// after\nexpect(msg).toEqual(expect.stringMatching(/error \\d+/))","handlingStrategy":"type-guard","validationCode":"function asStringOrRegex(v: unknown): string | RegExp {\n  if (typeof v !== 'string' && !(v instanceof RegExp)) {\n    throw new TypeError(`stringMatching needs string|RegExp, got ${typeof v}`)\n  }\n  return v\n}\nexpect(msg).toEqual(expect.stringMatching(asStringOrRegex(pattern)))","typeGuard":"function isStringOrRegExp(v: unknown): v is string | RegExp {\n  return typeof v === 'string' || v instanceof RegExp\n}","tryCatchPattern":null,"preventionTips":["Type pattern sources as string | RegExp.","Avoid passing flag-only objects; pass a real RegExp instance.","Add a lint rule catching non-string/RegExp args to stringMatching."],"tags":["expect","asymmetric-matcher","assertion","typescript"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}