karatelabs/karate · error · RuntimeException

multipart files expects a list or map:

Error message

multipart files expects a list or map: 

What it means

The `multipart files <expr>` step accepts either a List of file-part objects or a Map of part name to part object (V1 compatibility). If the evaluated value is neither, StepExecutor throws this RuntimeException with the step text.

Solutions

  1. Pass a list: `multipart files [{ read: 'a.txt', name: 'fileA' }, { read: 'b.txt', name: 'fileB' }]`.
  2. Or a map: `multipart files { fileA: { read: 'a.txt' }, fileB: { read: 'b.txt' } }`.
  3. Print the value before the step to confirm its shape.
  4. Fix the producing expression so it yields a list or map, not null/scalar.

Example fix

// before
* def f = 'not-a-list'
And multipart files f
// after
* def f = [{ name: 'fileA', read: 'data/a.txt' }]
And multipart files f
Defensive patterns

Strategy: type-guard

Validate before calling

* def files = myFiles || []
* assert typeof files == 'list' || typeof files == 'map'

Type guard

function isFileListOrMap(v) { return v != null && (Array.isArray(v) || typeof v === 'object'); }

Try / catch

try { scenario.run(step) } catch (RuntimeException e) { if (e.getMessage().startsWith("multipart files expects a list or map")) { /* normalize the value to a list/map first */ } throw e; }

Prevention

When it happens

Trigger: `multipart files` given a scalar, string, or null — e.g. a variable that failed to evaluate, or reusing a plain fields map where values are not file-part objects.

Common situations: Confusing `multipart fields` data with `multipart files` data; a JSON path or helper returning null; building the list in JS and returning the wrong type.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/3311740b455a5149. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/StepExecutor.java:2543

     * Also handles V1 map syntax: multipart files { myFile1: {...}, myFile2: {...} }
     * where map keys become the part names.
     */
    @SuppressWarnings("unchecked")
    private void executeMultipartFiles(Step step) {
        Object value = evalKarateExpression(step.getText());
        if (value instanceof List) {
            List<Object> files = (List<Object>) value;
            for (Object item : files) {
                processMultipartFileEntry(item, null);
            }
        } else if (value instanceof Map) {
            // V1 compatibility: map where keys are part names
            Map<String, Object> filesMap = (Map<String, Object>) value;
            for (Map.Entry<String, Object> entry : filesMap.entrySet()) {
                processMultipartFileEntry(entry.getValue(), entry.getKey());
            }
        } else {
            throw new RuntimeException("multipart files expects a list or map: " + step.getText());
        }
    }

    private void processMultipartFileEntry(Object item, String defaultName) {
        if (item instanceof Map) {
            @SuppressWarnings("unchecked")
            Map<String, Object> fileMap = (Map<String, Object>) item;
            Map<String, Object> multipartMap = new HashMap<>();

            // Name from map entry key (V1 compat) or from 'name' property
            String name = defaultName != null ? defaultName : (String) fileMap.get("name");
            if (name == null) {
                throw new RuntimeException("multipart files entry requires 'name': " + item);
            }
            multipartMap.put("name", name);

            // Handle file read
            Object readPath = fileMap.get("read");

View on GitHub (pinned to a22eb90246)