{"record":{"id":"627dc696c7e9622e","repo":"awslabs/llrt","slug":"you-must-provide-an-array-to-this-tostring-not-typeof-this","errorCode":null,"errorMessage":"You must provide an array to ${this.toString()}, not '${typeof this.sample}'.","messagePattern":"You must provide an array to (.+?), not '(.+?)'\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"llrt_core/src/modules/js/@llrt/expect/jest-asymmetric-matchers.ts","lineNumber":180,"sourceCode":"  }\n\n  toString() {\n    return `Object${this.inverse ? \"Not\" : \"\"}Containing`;\n  }\n\n  getExpectedType() {\n    return \"object\";\n  }\n}\n\nexport class ArrayContaining<T = unknown> extends AsymmetricMatcher<Array<T>> {\n  constructor(sample: Array<T>, inverse = false) {\n    super(sample, inverse);\n  }\n\n  asymmetricMatch(other: Array<T>) {\n    if (!Array.isArray(this.sample)) {\n      throw new TypeError(\n        `You must provide an array to ${this.toString()}, not '${typeof this\n          .sample}'.`\n      );\n    }\n\n    const result =\n      this.sample.length === 0 ||\n      (Array.isArray(other) &&\n        this.sample.every((item) =>\n          other.some((another) => equals(item, another, []))\n        ));\n\n    return this.inverse ? !result : result;\n  }\n\n  toString() {\n    return `Array${this.inverse ? \"Not\" : \"\"}Containing`;\n  }","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/awslabs/llrt/blob/742fc00b82cbeaab1c1b76f0d706c302a5cbc306/llrt_core/src/modules/js/@llrt/expect/jest-asymmetric-matchers.ts#L162-L198","documentation":"ArrayContaining.asymmetricMatch requires its sample to be an array and throws a TypeError otherwise, reporting the sample's typeof. This guards against constructing expect.arrayContaining with a scalar or object and silently getting failing/erratic matches.","triggerScenarios":"expect.arrayContaining(5), expect.arrayContaining('a,b'), or expect.arrayContaining({0:'x'}) — thrown when the matcher runs against a value.","commonSituations":"Passing a comma-joined string that was never split, passing arguments/iterables that are not real arrays, or API data that is an object map instead of a list.","solutions":["Pass a real array: expect.arrayContaining([1, 2]).","Convert the value with Array.from(value) or value.split(',') when appropriate.","Check the data source — the value may be an object or null where an array was expected.","Use expect.objectContaining for keyed collections instead."],"exampleFix":"// before\nexpect(ids).toEqual(expect.arrayContaining('1,2'));\n// after\nexpect(ids).toEqual(expect.arrayContaining('1,2'.split(',')));","handlingStrategy":"type-guard","validationCode":"if (!Array.isArray(sample)) throw new TypeError('arrayContaining sample must be an array');","typeGuard":"const isArr = <T>(v: unknown): v is T[] => Array.isArray(v);","tryCatchPattern":"try { expect(xs).toEqual(expect.arrayContaining(sample)); } catch (e) { /* inspect sample type and rebuild matcher */ }","preventionTips":["Split strings before passing: str.split(',')","Convert iterables with Array.from","Validate API list fields are arrays before building matchers","Prefer expect.arrayContaining([...]) with literal arrays in tests"],"tags":["testing","type-mismatch","asymmetric-matcher"],"backgroundTag":"invalid-argument-value","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"}