langgenius/dify · error · InvalidArgumentError

expected list for files, got {type(raw_value)}

Error message

expected list for files, got {type(raw_value)}

What it means

Returned (HTTP 400, `invalid_param`) by PATCH on a draft variable whose `value_type` is `SegmentType.ARRAY_FILE`. The handler requires `value` to be a JSON array (a list of file mappings) so it can be handed to `build_from_mappings`. Sending a dict, string, number, or any non-list raises InvalidArgumentError before the per-element checks run.

Source

Thrown at api/controllers/console/datasets/rag_pipeline/rag_pipeline_draft_variable.py:258

        new_name = args.get(self._PATCH_NAME_FIELD, None)
        raw_value = args.get(self._PATCH_VALUE_FIELD, None)
        if new_name is None and raw_value is None:
            return variable

        new_value = None
        if raw_value is not None:
            match variable.value_type:
                case SegmentType.FILE:
                    if not isinstance(raw_value, dict):
                        raise InvalidArgumentError(description=f"expected dict for file, got {type(raw_value)}")
                    raw_value = build_from_mapping(
                        mapping=raw_value,
                        tenant_id=pipeline.tenant_id,
                        access_controller=_file_access_controller,
                    )
                case SegmentType.ARRAY_FILE:
                    if not isinstance(raw_value, list):
                        raise InvalidArgumentError(description=f"expected list for files, got {type(raw_value)}")
                    if len(raw_value) > 0 and not isinstance(raw_value[0], dict):
                        raise InvalidArgumentError(description=f"expected dict for files[0], got {type(raw_value)}")
                    raw_value = build_from_mappings(
                        mappings=raw_value,
                        tenant_id=pipeline.tenant_id,
                        access_controller=_file_access_controller,
                    )
                case _:
                    pass
            new_value = build_segment_with_type(variable.value_type, raw_value)
        draft_var_srv.update_variable(variable, name=new_name, value=new_value)
        db.session.commit()
        return variable

    @console_ns.response(204, "Variable deleted successfully")
    @_api_prerequisite
    def delete(self, _current_user: Account, pipeline: Pipeline, variable_id: UUID):
        draft_var_srv = WorkflowDraftVariableService(

View on GitHub (pinned to ef8544b173)

Solutions

  1. Send `value` as a list: `[{...file mapping 1...}, {...file mapping 2...}]`.
  2. For zero files send an empty array `[]` rather than omitting the field (note: empty array still satisfies isinstance(list)).
  3. Verify `variable.value_type === 'array[file]'` on the client before constructing the payload.
  4. Double-check the form state returns an array even when one file is selected.

Example fix

// before
{ "value": { "type": "image", "transfer_method": "local_file", "upload_file_id": "<id>" } }
// after
{ "value": [ { "type": "image", "transfer_method": "local_file", "upload_file_id": "<id>" } ] }
Defensive patterns

Strategy: type-guard

Validate before calling

function asFileMappings(v: unknown): object[] {
  if (!Array.isArray(v)) {
    throw new Error('array[file] value must be a JSON array')
  }
  return v
}
// before PATCH for value_type === 'array[file]':
rawValue = asFileMappings(rawValue)

Type guard

function isFileArray(v: unknown): v is object[] {
  return Array.isArray(v)
}

Try / catch

try {
  await patch(...)
} catch (e) {
  if (e.code === 'invalid_param' && /expected list for files/.test(e.message)) {
    // wrap single object into [object] or rebuild array, then retry once
  } else throw e
}

Prevention

When it happens

Trigger: PATCHing an ARRAY_FILE variable with a single file object instead of a one-element list; sending `"value": { ... }`; sending a comma-separated string of ids.

Common situations: UI binding the multi-file picker to the first selected file rather than the array. Backend transforming the array into a single object during normalization. Confusing FILE vs ARRAY_FILE semantics.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/c72b5dae6cf79cf3. Report an issue: GitHub.