{"id":"e815340ad4f4c590","repo":"jestjs/jest","slug":"you-must-provide-an-object-to-this-tostring","errorCode":null,"errorMessage":"You must provide an object to ${this.toString()}, not '${typeof this.sample}'.","messagePattern":"You must provide an object to (.+?), not '(.+?)'\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/expect/src/asymmetricMatchers.ts","lineNumber":259,"sourceCode":"    return `${this.inverse ? 'Not' : ''}ArrayOf`;\n  }\n\n  override getExpectedType() {\n    return 'array';\n  }\n}\n\nclass ObjectContaining extends AsymmetricMatcher<\n  Record<string | symbol, unknown>\n> {\n  constructor(sample: Record<string | symbol, unknown>, inverse = false) {\n    super(sample, inverse);\n  }\n\n  asymmetricMatch(other: any) {\n    // Ensures that the argument passed to the objectContaining method is an object\n    if (typeof this.sample !== 'object') {\n      throw new TypeError(\n        `You must provide an object to ${this.toString()}, not '${typeof this\n          .sample}'.`,\n      );\n    }\n\n    // Ensures that the argument passed to the expect function is an object\n    // This is necessary to avoid matching of non-object values\n    // Arrays are a special type of object, but having a valid match with a standard object\n    // does not make sense, hence we do a simple array check\n    if (typeof other !== 'object' || Array.isArray(other)) {\n      return false;\n    }\n\n    let result = true;\n\n    const matcherContext = this.getMatcherContext();\n    const objectKeys = getObjectKeys(this.sample);\n","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/jestjs/jest/blob/f49721c78e195558b40913977c9230f5b7f559d8/packages/expect/src/asymmetricMatchers.ts#L241-L277","documentation":"ObjectContaining.asymmetricMatch requires typeof this.sample === 'object'; if a primitive (string/number/boolean/function/undefined/symbol/bigint) was passed to expect.objectContaining it throws TypeError. The matcher checks at match time (constructor only stores the sample). Note typeof null === 'object' so null slips past this guard but will then iterate over no keys.","triggerScenarios":"Calling expect.objectContaining('foo'), expect.objectContaining(42), expect.objectContaining(undefined), or expect.objectContaining(() => {}) and then evaluating that matcher in a comparison.","commonSituations":"Confusing objectContaining with stringMatching/arrayContaining; passing a class instead of an instance descriptor; passing a JSON string instead of a parsed object.","solutions":["Pass a plain object describing the subset of keys/values: expect.objectContaining({ id: 5 }).","Parse JSON first if you have a string: expect.objectContaining(JSON.parse(str)).","Use the correct matcher for primitives: expect.stringContaining, expect.arrayContaining, etc."],"exampleFix":"// before\nexpect(received).toEqual(expect.objectContaining('{\"id\":5}'));\n\n// after\nexpect(received).toEqual(expect.objectContaining({ id: 5 }));","handlingStrategy":"type-guard","validationCode":"if (typeof sample !== 'object' || sample === null || Array.isArray(sample)) {\n  throw new TypeError('expect.objectContaining needs a plain object');\n}\nexpect.objectContaining(sample);","typeGuard":"function isPlainObject(x: unknown): x is Record<string | symbol, unknown> {\n  return typeof x === 'object' && x !== null && !Array.isArray(x);\n}","tryCatchPattern":"// throws at match time; guard the sample before constructing the matcher","preventionTips":["Pass plain object literals: expect.objectContaining({ id: 5 }).","Parse JSON strings before passing them.","Remember typeof null === 'object' — also exclude null and arrays."],"tags":["expect","asymmetric-matcher","type-error","object"],"analyzedSha":"f49721c78e195558b40913977c9230f5b7f559d8","analyzedAt":"2026-08-03T20:16:28.571Z","schemaVersion":2}