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
- Send `value` as a list: `[{...file mapping 1...}, {...file mapping 2...}]`.
- For zero files send an empty array `[]` rather than omitting the field (note: empty array still satisfies isinstance(list)).
- Verify `variable.value_type === 'array[file]'` on the client before constructing the payload.
- 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
- Always build an array (even for a single file) when value_type is `array[file]`.
- Distinguish FILE vs ARRAY_FILE in the UI binding.
- Add a form-level assertion that the multi-file picker yields an array.
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
- expected dict for file, got {type(raw_value)}
- expected dict for files[0], got {type(raw_value)}
- Draft workflow not found, pipeline_id={pipeline.id}
- draft_workflow_not_exist
- draft_workflow_not_exist
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/c72b5dae6cf79cf3.
Report an issue: GitHub.