{"record":{"id":"e0310d39c9adbb16","repo":"karatelabs/karate","slug":"karate-call-arg-must-be-a-map-or-list-got-class","errorCode":null,"errorMessage":"karate.call() arg must be a map or list, got: <class>","messagePattern":"karate\\.call\\(\\) arg must be a map or list, got: <class>","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/core/ScenarioRuntime.java","lineNumber":619,"sourceCode":"                }\n                // Non-callable JS (e.g. an object/JSON literal file) — return as-is.\n                return jsTarget;\n            }\n            calledFeature = Feature.read(calledResource);\n        }\n\n        // Array-loop call - delegate to shared helper used by the `call` keyword\n        if (arg instanceof List) {\n            return executor.callFeatureLoop(calledFeature, (List<?>) arg, tagSelector, lineFilters);\n        }\n\n        // Single call - arg must be a map (or null)\n        Map<String, Object> callArg = null;\n        if (arg != null) {\n            if (arg instanceof Map) {\n                callArg = (Map<String, Object>) arg;\n            } else {\n                throw new RuntimeException(\"karate.call() arg must be a map or list, got: \" + arg.getClass());\n            }\n        }\n\n        Map<String, Object> resultVars = executor.callFeatureSingle(calledFeature, callArg, tagSelector, lineFilters);\n        return resultVars != null ? resultVars : new HashMap<>();\n    }\n\n    /**\n     * Execute karate.callonce() - runs a feature once per FeatureRuntime and caches the result.\n     * Uses the same cache as the callonce keyword.\n     * Uses double-check locking to ensure thread-safe execution in parallel scenarios.\n     */\n    public Object executeJsCallOnce(String path, Object arg) {\n        if (featureRuntime == null) {\n            throw new RuntimeException(\"karate.callonce() requires a feature context\");\n        }\n\n        // Use the same cache key format as the keyword: \"callonce:call read('path')\"","sourceCodeStart":601,"sourceCodeEnd":637,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/core/ScenarioRuntime.java#L601-L637","documentation":"karate.call() accepts an optional second argument that must be a Map (or null) for a single call, or a List to loop-call. When a single (non-list) call is given any other type — string, number, boolean, function — this RuntimeException is thrown naming the offending Java class.","triggerScenarios":"karate.call('path.feature', arg) where arg is a JS primitive (e.g. a string id), a function, or any non-Map non-List value; passing a JSON string instead of a parsed object.","commonSituations":"Passing a single scalar instead of wrapping it in an object; reading JSON from a file as text and passing it without parsing; a JS function reference typed where its result was intended.","solutions":["Wrap scalar arguments in a map: karate.call('path.feature', { id: myId }).","If you intend per-element calls, pass a JS array (List) instead of a single object.","Parse JSON strings before passing: JSON.parse(str) or karate.read of a .json file.","Call the function first and pass its result, not the function reference itself."],"exampleFix":"// before\n* def result = karate.call('classpath:user.feature', userId)\n\n// after\n* def result = karate.call('classpath:user.feature', { userId: '#(userId)' })","handlingStrategy":"validation","validationCode":"// before calling\nvar arg = karate.get('payload');\nif (arg != null && !(arg instanceof Map) && !Array.isArray(arg)) {\n    karate.log('normalizing arg to map:', typeof arg);\n    arg = { value: arg };\n}\nvar result = karate.call('classpath:user.feature', arg);","typeGuard":"function isCallArg(a) {\n  return a == null || a instanceof Map || Array.isArray(a);\n}\nif (!isCallArg(payload)) payload = { value: payload };","tryCatchPattern":"try {\n    var result = karate.call('classpath:user.feature', payload);\n} catch (e) {\n    if (String(e).indexOf('arg must be a map or list') >= 0) {\n        result = karate.call('classpath:user.feature', { value: payload });\n    } else { throw e; }\n}","preventionTips":["Always pass objects (maps) or arrays as call args, never scalars","Parse JSON strings with JSON.parse before passing","Invoke functions first; pass results, not function references","Wrap single scalar IDs in a named field: { id: myId }"],"tags":["karate-call","type-mismatch","karate-js"],"backgroundTag":"type-mismatch","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}