karatelabs/karate · error · TypeError
String.raw .raw must be an object
Error message
String.raw .raw must be an object
What it means
This TypeError is thrown by String.raw when the 'raw' property of the template object is not itself an object. The spec requires call(template.raw) where raw must be an Object-like carrying a 'length' and indexed elements. A raw value that is a string, number, or undefined-but-coercible value triggers this error.
Solutions
- Give the template object an array (or object with length) as raw: { raw: ['a','b'] }
- Check Array.isArray(template.raw) before calling String.raw
- Use an actual tagged template literal so the runtime builds a correct template object
Example fix
// before
String.raw({ raw: 'abc' }); // TypeError
// after
String.raw({ raw: ['a', 'b', 'c'] }); // 'abc' Defensive patterns
Strategy: type-guard
Validate before calling
const hasRawObject = (t) => t !== null && typeof t === 'object' && t.raw !== null && typeof t.raw === 'object';
Type guard
const isRawTemplate = (t) => typeof t === 'object' && t !== null && typeof t.raw === 'object' && t.raw !== null && typeof t.raw.length === 'number';
Try / catch
try { return String.raw(template); } catch (e) { if (e instanceof TypeError) return ''; throw e; } Prevention
- Ensure raw is an array of string parts, not a single string
- Keep template objects intact through serialization/destructuring
- Add a shape assertion when constructing template-like mocks
When it happens
Trigger: Calling String.raw({ raw: 'abc' }) — a string raw is rejected — or String.raw({}) where raw is undefined (after requireObjectCoercible on undefined), or passing an object whose raw property was overwritten with a non-object.
Common situations: Hand-built template-like objects for testing; destructured or serialized template objects losing the raw array; mock libraries that approximate template objects incorrectly.
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
- String.raw template must be an object
- String.prototype.replaceAll called with a non-global RegExp…
- String.prototype.valueOf requires that 'this' be a String
- toBytes() argument must be a list of numbers, got
- toBytes() list must contain only numbers, got
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/b552624852f61e04.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsStringConstructor.java:97
return sb.toString();
}
// Spec §22.1.2.4 — String.raw(template, ...substitutions). Walks
// template.raw[k] for k in [0, length), interleaving substitutions[k] from
// the second arg onward. Coercion goes through the spec ToString helper so
// host objects with a JS toString return user-visible strings, and
// non-array-like raw values (length=NaN/0) fall through to the empty
// string per §22.1.2.4 step 6 / 8.
private Object raw(Context context, Object[] args) {
Object template = args.length > 0 ? args[0] : Terms.UNDEFINED;
Terms.requireObjectCoercible(template, "String.raw");
if (!(template instanceof ObjectLike templateObj)) {
throw JsErrorException.typeError("String.raw template must be an object");
}
Object rawObj = templateObj.getMember("raw");
Terms.requireObjectCoercible(rawObj, "String.raw .raw");
if (!(rawObj instanceof ObjectLike raw)) {
throw JsErrorException.typeError("String.raw .raw must be an object");
}
CoreContext cc = context instanceof CoreContext c ? c : null;
// Spec ToLength(raw.length): NaN / negative / undefined → 0.
double rawLen = Terms.objectToNumber(raw.getMember("length")).doubleValue();
if (Double.isNaN(rawLen) || rawLen <= 0) return "";
long length = rawLen >= Integer.MAX_VALUE ? Integer.MAX_VALUE : (long) rawLen;
StringBuilder sb = new StringBuilder();
for (long i = 0; i < length; i++) {
sb.append(Terms.toStringCoerce(raw.getMember(Long.toString(i)), cc));
if (i + 1 == length) break;
// substitutions are positional starting at args[1].
int subIdx = (int) (i + 1);
if (subIdx < args.length) {
sb.append(Terms.toStringCoerce(args[subIdx], cc));
}
}
return sb.toString();
}View on GitHub (pinned to a22eb90246)