karatelabs/karate · error · RuntimeException
embed(): each part needs a 'role'
Error message
embed(): each part needs a 'role'
What it means
Validation in toMultiPartEmbed, the map-form of embed(): every entry in the 'parts' list must carry a 'role' key so the multipart body part can be classified (e.g. form-field vs file). Fires when a part object omits 'role'; add a role to each part.
Solutions
- Add a role string to every part object: {role: 'screenshot', path: 'a.png'}.
- Ensure the role value is not JS null/undefined at build time.
- Keep roles descriptive and consistent across steps for readable reports.
Example fix
// before
karate.embed({ parts: [{ path: 'a.png' }] });
// after
karate.embed({ parts: [{ role: 'screenshot', path: 'a.png' }] }); Defensive patterns
Strategy: validation
Validate before calling
if (parts.some(function(p){ return p == null || p.role == null; })) { throw new Error('each part needs a role'); } Type guard
function hasRole(p) { return p != null && typeof p === 'object' && typeof p.role === 'string' && p.role.length > 0; } Try / catch
try { karate.embed({ parts: parts }); } catch (e) { if (String(e.message).includes("needs a 'role'")) { karate.log('part missing role'); } throw e; } Prevention
- Give every part a descriptive role string
- Check role variables are set when building parts dynamically
- Standardize role names across your project's reporting
When it happens
Trigger: karate.embed({parts: [{path: 'a.png'}]}) or parts objects built dynamically where role was omitted or set to null.
Common situations: Hand-writing embed payloads and forgetting role; dynamic part construction where the role variable was undefined; migrating single embeds to multipart form without adding roles.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- embed(): each 'parts' entry must be an object
- embed(): part ' ' needs 'data', 'path', or 'url
- embed() needs at least one argument: data
- doc() called, but no destination set
- read() needs at least one argument
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/08e210aa757e6bf2.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/core/KarateJsBase.java:530
? args[1].toString() : KarateJsUtils.detectMimeType(first);
String name = args.length > 2 ? args[2].toString() : null;
byte[] data = KarateJsUtils.convertToBytes(first);
LogContext.get().embed(data, mimeType, name);
return null;
};
}
private StepResult.Embed toMultiPartEmbed(Map<?, ?> map) {
String name = map.get("name") != null ? map.get("name").toString() : null;
List<StepResult.Part> parts = new ArrayList<>();
for (Object partObj : (List<?>) map.get("parts")) {
Object pu = unwrapJs(partObj);
if (!(pu instanceof Map<?, ?> pm)) {
throw new RuntimeException("embed(): each 'parts' entry must be an object");
}
Object roleObj = pm.get("role");
if (roleObj == null) {
throw new RuntimeException("embed(): each part needs a 'role'");
}
String role = roleObj.toString();
String mime = pm.get("mime") != null ? pm.get("mime").toString() : null;
Object url = pm.get("url");
if (url != null) {
parts.add(new StepResult.Part(role, mime, url.toString()));
continue;
}
byte[] bytes;
Object dataObj = pm.get("data");
Object pathObj = pm.get("path");
if (dataObj != null) {
bytes = KarateJsUtils.convertToBytes(unwrapJs(dataObj));
} else if (pathObj != null) {
bytes = readPathBytes(pathObj.toString());
} else {
throw new RuntimeException("embed(): part '" + role + "' needs 'data', 'path', or 'url'");
}View on GitHub (pinned to a22eb90246)