{"record":{"id":"1993f5f3a9b35e80","repo":"awslabs/llrt","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":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"llrt_core/src/modules/js/@llrt/expect/jest-asymmetric-matchers.ts","lineNumber":277,"sourceCode":"\n    if (this.sample === Function) return \"function\";\n\n    if (this.sample === Object) return \"object\";\n\n    if (this.sample === Boolean) return \"boolean\";\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    super(new RegExp(sample), inverse);\n  }\n\n  asymmetricMatch(other: string) {\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  }\n}","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/awslabs/llrt/blob/742fc00b82cbeaab1c1b76f0d706c302a5cbc306/llrt_core/src/modules/js/@llrt/expect/jest-asymmetric-matchers.ts#L259-L295","documentation":"StringMatching builds a RegExp from its sample, which must be a string or a RegExp. The constructor throws this plain Error for any other type so invalid patterns fail fast instead of producing a runtime RegExp construction error inside matching.","triggerScenarios":"expect.stringMatching(42), expect.stringMatching(null), expect.stringMatching({pattern:'x'}) — any sample that is neither string nor RegExp.","commonSituations":"Passing a regex-like object from another library, passing a number pattern, or a variable expected to hold a pattern string that is undefined.","solutions":["Pass a string pattern: expect.stringMatching('^abc$').","Pass a RegExp literal: expect.stringMatching(/abc/i).","Convert a RegExp-like object to a real RegExp via new RegExp(obj.pattern, obj.flags).","Fix the undefined variable holding the pattern."],"exampleFix":"// before\nexpect(err.message).toEqual(expect.stringMatching(404));\n// after\nexpect(err.message).toEqual(expect.stringMatching(/404/));","handlingStrategy":"type-guard","validationCode":"if (typeof sample !== 'string' && !(sample instanceof RegExp)) throw new TypeError('stringMatching sample must be a string or RegExp');","typeGuard":"const isPattern = (v: unknown): v is string | RegExp => typeof v === 'string' || v instanceof RegExp;","tryCatchPattern":"try { expect(msg).toEqual(expect.stringMatching(sample)); } catch (e) { /* bad pattern sample */ }","preventionTips":["Use RegExp literals for patterns whenever possible","Validate config-supplied patterns are strings","Avoid passing regex-like objects from other libraries","Keep pattern strings in typed constants"],"tags":["testing","validation","regex","asymmetric-matcher"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"742fc00b82cbeaab1c1b76f0d706c302a5cbc306","analyzedAt":"2026-09-12T11:14:07.838Z","contentChangedAt":"2026-09-12T11:14:07.838Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}