awslabs/llrt · error · Error
Expected is not a string
Error message
Expected is not a string
What it means
StringContaining is an asymmetric matcher that checks whether another string includes the given sample substring. The constructor validates that the sample is actually a string using isA("String", sample) and throws this plain Error if not, so malformed matchers fail fast instead of silently never matching. It mirrors Jest's own validation for expect.stringContaining.
Solutions
- Convert the sample to a string before passing it, e.g. expect.stringContaining(String(value)).
- Verify the variable actually holds a string; fix the source of the non-string value (often an API response field or undefined variable).
- Use expect.any(String) instead if you only care that the value is a string.
- Use expect.arrayContaining/objectContaining if you meant to match a non-string structure.
Example fix
// before expect(log).toEqual(expect.stringContaining(404)); // after expect(log).toEqual(expect.stringContaining(String(404)));
Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof sample !== 'string') throw new TypeError('stringContaining sample must be a string'); Type guard
const isStr = (v: unknown): v is string => typeof v === 'string';
Try / catch
try { expect(x).toEqual(expect.stringContaining(s)); } catch (e) { if (!(e instanceof Error) || !/Expected is not a string/.test(e.message)) throw e; /* handle bad sample */ } Prevention
- Always pass string literals or values narrowed to string
- Enable TypeScript strict mode so non-strings are flagged at compile time
- Prefer expect.any(String) when validating type only
- Check for undefined variables that commonly carry the substring
When it happens
Trigger: Calling expect.stringContaining(x) (or expect.not.stringContaining(x)) where x is not a string — e.g. a number, null, undefined, or an object.
Common situations: Passing a number that looks like text (stringContaining(123)), passing a variable that is undefined due to a typo or failed lookup, or copying matchers between expect().toContain and expect().toStrictEqual where argument types differ.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Expected is not a String or a RegExp
- Expected is not a Number
- Precision is not a Number
- You must provide an object to
- You must provide an array to
AI-assisted analysis of awslabs/llrt@742fc00b82 (2026-09-12).
Data as JSON: /api/errors/fb7acd81127ff196.
Report an issue: GitHub.
Appendix: source
Thrown at llrt_core/src/modules/js/@llrt/expect/jest-asymmetric-matchers.ts:83
abstract asymmetricMatch(other: unknown): boolean;
abstract toString(): string;
getExpectedType?(): string;
toAsymmetricMatcher?(): string;
// implement custom chai/loupe inspect for better AssertionError.message formatting
// https://github.com/chaijs/loupe/blob/9b8a6deabcd50adc056a64fb705896194710c5c6/src/index.ts#L29
[Symbol.for("chai/inspect")](options: { depth: number; truncate: number }) {
// minimal pretty-format with simple manual truncation
const result = stringify(this, options.depth, { min: true });
if (result.length <= options.truncate) return result;
return `${this.toString()}{…}`;
}
}
export class StringContaining extends AsymmetricMatcher<string> {
constructor(sample: string, inverse = false) {
if (!isA("String", sample)) throw new Error("Expected is not a string");
super(sample, inverse);
}
asymmetricMatch(other: string) {
const result = isA("String", other) && other.includes(this.sample);
return this.inverse ? !result : result;
}
toString() {
return `String${this.inverse ? "Not" : ""}Containing`;
}
getExpectedType() {
return "string";
}
}View on GitHub (pinned to 742fc00b82)