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

  1. Give the template object an array (or object with length) as raw: { raw: ['a','b'] }
  2. Check Array.isArray(template.raw) before calling String.raw
  3. 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

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


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)