{"id":"969c3d0e44c59227","repo":"vitest-dev/vitest","slug":"received-value-must-be-an-object-when-the-matcher","errorCode":null,"errorMessage":"Received value must be an object when the matcher has properties","messagePattern":"Received value must be an object when the matcher has properties","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/snapshot/src/client.ts","lineNumber":151,"sourceCode":"    if (!filepath) {\n      throw new Error('Snapshot cannot be used outside of test')\n    }\n\n    const snapshotState = this.getSnapshotState(filepath)\n    const testName = [name, ...(message ? [message] : [])].join(' > ')\n\n    // Probe first so we can mark as checked even on early return\n    const expectedSnapshot = snapshotState.probeExpectedSnapshot({\n      testName,\n      testId,\n      isInline,\n      inlineSnapshot,\n    })\n\n    if (typeof properties === 'object') {\n      if (typeof received !== 'object' || !received) {\n        expectedSnapshot.markAsChecked()\n        throw new Error(\n          'Received value must be an object when the matcher has properties',\n        )\n      }\n\n      let propertiesPass: boolean\n      try {\n        propertiesPass = this.options.isEqual?.(received, properties) ?? false\n      }\n      catch (err) {\n        expectedSnapshot.markAsChecked()\n        throw err\n      }\n      if (!propertiesPass) {\n        expectedSnapshot.markAsChecked()\n        return {\n          pass: false,\n          message: () => errorMessage || 'Snapshot properties mismatched',\n          actual: received,","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/snapshot/src/client.ts#L133-L169","documentation":"Thrown by SnapshotClient.match() when the second 'properties' argument is provided (an object of asymmetric matchers / expected subset) but the received value is not a non-null object. Vitest needs an object to deep-merge the properties hint against the received value before serializing; primitives and null/undefined cannot be subset-matched. The library throws rather than silently producing a misleading snapshot.","triggerScenarios":"expect('string').toMatchSnapshot({ length: 5 }); expect(null).toMatchSnapshot({ foo: expect.any(String) }); expect(42).toMatchSnapshot({}); passing a properties hint to toMatchSnapshot while the received value is a primitive, null, or undefined.","commonSituations":"Refactor that changed a function return from object to string but kept the properties matcher; using the properties overload by mistake (passing a second argument intended as a message); testing JSON that parsed to a non-object.","solutions":["Ensure the received value passed to expect() is a non-null object before using the properties overload.","Drop the properties argument if you intended the second arg to be a snapshot name/message.","Wrap the assertion so it only runs when the value is an object: if (typeof value === 'object' && value) expect(value).toMatchSnapshot({...}).","Update the test to reflect the new return type of the code under test."],"exampleFix":"// before\nexpect(getName()).toMatchSnapshot({ length: expect.any(Number) })\n\n// after\nexpect(getName()).toMatchSnapshot() // getName() returns a string","handlingStrategy":"type-guard","validationCode":"const isObj = (v: unknown): v is Record<string, unknown> =>\n  typeof v === 'object' && v !== null\nif (isObj(received)) {\n  expect(received).toMatchSnapshot({ id: expect.any(Number) })\n} else {\n  expect(received).toMatchSnapshot()\n}","typeGuard":"const isPlainObject = (v: unknown): v is Record<string, unknown> =>\n  typeof v === 'object' && v !== null && !Array.isArray(v)","tryCatchPattern":null,"preventionTips":["Only pass the properties hint when the received value is statically known to be an object.","Reserve the second argument of toMatchSnapshot for object subset matching; use the string overload for naming.","Add a TypeScript helper that constrains the properties overload to object receivers."],"tags":["snapshot","assertion","type-mismatch"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}