{"record":{"id":"3dc39d13611a45f8","repo":"jestjs/jest","slug":"expected-color-expected-value-must-be-a-stri","errorCode":null,"errorMessage":"${EXPECTED_COLOR('expected')} value must be a string if ${RECEIVED_COLOR('received')} value is a string","messagePattern":"(.+?) value must be a string if (.+?) value is a string","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/expect/src/matchers.ts","lineNumber":492,"sourceCode":"    if (received == null) {\n      throw new Error(\n        matcherErrorMessage(\n          matcherHint(matcherName, undefined, undefined, options),\n          `${RECEIVED_COLOR('received')} value must not be null nor undefined`,\n          printWithType('Received', received, printReceived),\n        ),\n      );\n    }\n\n    if (typeof received === 'string') {\n      const wrongTypeErrorMessage = `${EXPECTED_COLOR(\n        'expected',\n      )} value must be a string if ${RECEIVED_COLOR(\n        'received',\n      )} value is a string`;\n\n      if (typeof expected !== 'string') {\n        throw new TypeError(\n          matcherErrorMessage(\n            matcherHint(matcherName, received, String(expected), options),\n            wrongTypeErrorMessage,\n            // eslint-disable-next-line prefer-template\n            printWithType('Expected', expected, printExpected) +\n              '\\n' +\n              printWithType('Received', received, printReceived),\n          ),\n        );\n      }\n\n      const index = received.indexOf(String(expected));\n      const pass = index !== -1;\n\n      const message = () => {\n        const labelExpected = `Expected ${\n          typeof expected === 'string' ? 'substring' : 'value'\n        }`;","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/jestjs/jest/blob/8e6d128e4a278059ecddecaa97400b04c8ae5fd9/packages/expect/src/matchers.ts#L474-L510","documentation":"Thrown by `toContain` (matchers.ts:491) when the received value is a string but the expected value is not a string. Because string containment uses `String.indexOf`, the expected argument must also be a string; the matcher refuses to silently coerce a non-string (which would hide a real bug).","triggerScenarios":"Calling `expect('hello world').toContain(5)` (number), `toContain(/world/)` (regex), or `toContain({a:1})` (object). The received is a string, so indexOf semantics require a string expected.","commonSituations":"Developer intends substring search but passes a number/object; confusing toContain (substring) with toMatch (regex); passing a value from a typed source that is not a string; copy-paste from an array test where toContain takes any value.","solutions":["Pass a string substring: toContain('world'), not toContain(5) or toContain(/world/).","If you need a regex match, use toMatch instead of toContain.","If testing array membership (non-string received), ensure the received value is actually an array.","Coerce the expected to a string with String(...) only if that is genuinely intended."],"exampleFix":"// before\nexpect('hello world').toContain(/world/);\nexpect('items: 5').toContain(5);\n\n// after\nexpect('hello world').toContain('world');\n// regex belongs in toMatch\nexpect('hello world').toMatch(/world/);\n// coerce only if intended\nexpect('items: 5').toContain(String(5));","handlingStrategy":"type-guard","validationCode":"const needle = searchValue;\nif (typeof received === 'string' && typeof needle !== 'string') {\n  throw new Error('when received is a string, expected must also be a string');\n}\nexpect(received).toContain(needle);","typeGuard":"const isStringNeedle = (received: unknown, expected: unknown): expected is string =>\n  typeof received === 'string' ? typeof expected === 'string' : true;","tryCatchPattern":null,"preventionTips":["Use toMatch for regex and toContain for substring; keep them distinct.","When received is a string, always pass a string substring.","Add TS types so the expected type aligns with received."],"tags":["jest","expect","matcher","type-error","tocontain","string"],"backgroundTag":null,"analyzedSha":"8e6d128e4a278059ecddecaa97400b04c8ae5fd9","analyzedAt":"2026-08-10T18:11:27.960Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}