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

  1. Ensure mask is a map, e.g. 'configure logging = { mask: { headers: ["Authorization"], jsonPaths: ["$.password"], patterns: [] } }'
  2. Alternatively use the declarative form 'configure logging = { mask: { headers: [...], jsonPaths: [...], patterns: [...] } }' as documented in the error text for configure mask
  3. 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

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


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)