karatelabs/karate · error · TypeError
String.raw template must be an object
Error message
String.raw template must be an object
What it means
This TypeError is thrown by String.raw when its first argument is not an object. String.raw is designed for tagged template literals where the first argument is a template object with a 'raw' array property. Passing a non-object (string, number, undefined via requireObjectCoercible pass, etc.) makes the template shape invalid.
Solutions
- Use String.raw as a template tag: String.raw`text` instead of String.raw('text')
- Pass an object with a raw property: String.raw({ raw: ['a','b'] })
- Guard the argument: if (typeof v !== 'object' || v === null) fall back to String(v)
Example fix
// before
const s = String.raw('a\nb'); // TypeError
// after
const s = String.raw`a\nb`; Defensive patterns
Strategy: type-guard
Validate before calling
const isTemplateObj = (v) => v !== null && typeof v === 'object' && v.raw !== undefined;
Type guard
const canStringRaw = (v) => v !== null && typeof v === 'object' && Array.isArray(v.raw);
Try / catch
try { return String.raw(templateObj); } catch (e) { if (e instanceof TypeError) return String(templateObj); throw e; } Prevention
- Only use String.raw as a template tag (String.raw`...`), never as a plain function
- Validate template objects have a raw property before forwarding them
- When synthesizing template objects, mimic the runtime shape: { raw: [...], cooked: [...] }
When it happens
Trigger: Calling String.raw directly with a plain value: String.raw('abc') or String.raw(42). Note undefined/null fail earlier at requireObjectCoercible with a different message; this error fires for coercible-but-non-object values like strings and numbers.
Common situations: Calling String.raw as a normal string function instead of a tag; refactorings that removed the template literal; library code forwarding user values into String.raw.
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 .raw 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/8445163b561dff4c.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsStringConstructor.java:92
throw JsErrorException.rangeError("Invalid code point " + num);
}
sb.appendCodePoint(n);
}
}
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) {View on GitHub (pinned to a22eb90246)