karatelabs/karate · error · RuntimeException
configure 'logging.mask' expects a map, got
Error message
configure 'logging.mask' expects a map, got: ${maskValue.getClass().getName()} What it means
Within 'configure logging', the optional 'mask' key must itself be a Map matching LogMask.fromMap's expected shape ({ headers: [...], jsonPaths: [...], patterns: [...] }). If mask is present but not a Map, configureLogging throws with the value's class name.
Solutions
- Ensure mask is a map, e.g. 'configure logging = { mask: { headers: ["Authorization"], jsonPaths: ["$.password"], patterns: [] } }'
- Alternatively use the declarative form 'configure logging = { mask: { headers: [...], jsonPaths: [...], patterns: [...] } }' as documented in the error text for configure mask
- Print the value with karate.log before configuring to confirm its type
Example fix
// before
* configure logging = { mask: 'mask-config.json' }
// after
* configure logging = { mask: { headers: ['Authorization'], jsonPaths: ['$.password'], patterns: [] } } Defensive patterns
Strategy: type-guard
Validate before calling
var isValidMask = function (m) { return m !== null && typeof m === 'object' && !(m instanceof Array); }; Type guard
function isMaskMap(logging) { return !logging.mask || (typeof logging.mask === 'object' && !Array.isArray(logging.mask)); } Try / catch
try { karate.configure('logging', cfg); } catch (RuntimeException e) { if (e.getMessage().contains("logging.mask' expects a map")) { log.error('mask must be { headers, jsonPaths, patterns } object'); } throw e; } Prevention
- Keep mask as an inline object literal, not a path string
- Verify nested structure: logging.mask, not logging.mask.headers at top level
- Unit-test karate-config.js config construction
When it happens
Trigger: 'configure logging = { mask: "headers.json" }' or mask set to a list/string/other non-map value; a JS variable holding the mask config that resolves to null or an unexpected type.
Common situations: Passing a file path string where an inline mask map is expected; building the mask object in JS and accidentally assigning the wrong variable; copy-pasting mask config in the wrong nesting level (mask directly under logging but as a scalar).
Related errors
- configure 'logging' expects a map, got
- 'configure report = ' is no longer supported; use…
- Class must implement RunListenerFactory or RunListener
- Invalid callbackPort type: " + portValue.getClass()
- Invalid callbackPorts type: " + portsValue.getClass()
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/34288f5110ed9322.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/core/KarateConfig.java:656
boolean pretty = toBoolean(map.get("pretty"));
this.logging.put("pretty", pretty);
LogContext.get().setPretty(pretty);
}
if (map.containsKey("mask")) {
Object maskValue = map.get("mask");
if (maskValue == null) {
this.logging.remove("mask");
this.compiledMask = null;
LogContext.get().setMask(null);
} else if (maskValue instanceof Map<?, ?> maskMap) {
@SuppressWarnings("unchecked")
Map<String, Object> mm = (Map<String, Object>) maskMap;
LogMask compiled = LogMask.fromMap(mm);
this.logging.put("mask", mm);
this.compiledMask = compiled;
LogContext.get().setMask(compiled);
} else {
throw new RuntimeException("configure 'logging.mask' expects a map, got: " + maskValue.getClass().getName());
}
}
}
/**
* Push this config's logging settings into the given LogContext.
* Called by {@link ScenarioRuntime#call()} after it allocates a fresh thread-local
* LogContext, so any mask / pretty values set in karate-config.js (or a prior step)
* survive into the scenario's HTTP logging.
*/
public void applyLoggingToContext(LogContext ctx) {
if (ctx == null) return;
ctx.setMask(compiledMask);
Object prettyVal = logging.get("pretty");
ctx.setPretty(prettyVal == null ? true : toBoolean(prettyVal));
}
/**View on GitHub (pinned to a22eb90246)