{"record":{"id":"65b9eb37919f222d","repo":"langgenius/dify","slug":"expected-dict-for-files-0-got-type-raw-value","errorCode":null,"errorMessage":"expected dict for files[0], got {type(raw_value)}","messagePattern":"expected dict for files\\[0\\], got (.+?)","errorType":"validation","errorClass":"InvalidArgumentError","httpStatus":400,"severity":"error","filePath":"api/controllers/console/datasets/rag_pipeline/rag_pipeline_draft_variable.py","lineNumber":260,"sourceCode":"        if new_name is None and raw_value is None:\n            return variable\n\n        new_value = None\n        if raw_value is not None:\n            match variable.value_type:\n                case SegmentType.FILE:\n                    if not isinstance(raw_value, dict):\n                        raise InvalidArgumentError(description=f\"expected dict for file, got {type(raw_value)}\")\n                    raw_value = build_from_mapping(\n                        mapping=raw_value,\n                        tenant_id=pipeline.tenant_id,\n                        access_controller=_file_access_controller,\n                    )\n                case SegmentType.ARRAY_FILE:\n                    if not isinstance(raw_value, list):\n                        raise InvalidArgumentError(description=f\"expected list for files, got {type(raw_value)}\")\n                    if len(raw_value) > 0 and not isinstance(raw_value[0], dict):\n                        raise InvalidArgumentError(description=f\"expected dict for files[0], got {type(raw_value)}\")\n                    raw_value = build_from_mappings(\n                        mappings=raw_value,\n                        tenant_id=pipeline.tenant_id,\n                        access_controller=_file_access_controller,\n                    )\n                case _:\n                    pass\n            new_value = build_segment_with_type(variable.value_type, raw_value)\n        draft_var_srv.update_variable(variable, name=new_name, value=new_value)\n        db.session.commit()\n        return variable\n\n    @console_ns.response(204, \"Variable deleted successfully\")\n    @_api_prerequisite\n    def delete(self, _current_user: Account, pipeline: Pipeline, variable_id: UUID):\n        draft_var_srv = WorkflowDraftVariableService(\n            session=db.session(),\n        )","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/datasets/rag_pipeline/rag_pipeline_draft_variable.py#L242-L278","documentation":"Returned (HTTP 400, `invalid_param`) by PATCH on an ARRAY_FILE variable when `value` is a non-empty list but its first element is not a dict. The handler checks `raw_value[0]` to fail fast before calling `build_from_mappings`, which would otherwise crash on a non-mapping element. Note the error message string still prints `type(raw_value)` (the list) rather than the element type — a known cosmetic bug.","triggerScenarios":"Sending `\"value\": [\"<upload_file_id>\"]` (list of strings) instead of a list of objects; mixing object and string elements with a string at index 0; passing a list parsed from a flat CSV.","commonSituations":"Frontend mapping over selected files and emitting only their ids. API gateway that flattens nested objects. Test fixtures building the array from string columns.","solutions":["Ensure every element of the `value` array is a file-mapping object.","Map each id to its object before send: `value: ids.map(id => ({ type, transfer_method, upload_file_id: id }))`.","Reject mixed-type arrays client-side before PATCH.","When the list is non-empty, validate `Array.isArray(value) && value.every(v => v && typeof v === 'object')`."],"exampleFix":"// before\n{ \"value\": [ \"daded54f-72c7-4f8e-9d18-9b0abdd9f190\" ] }\n// after\n{ \"value\": [ { \"type\": \"image\", \"transfer_method\": \"local_file\", \"upload_file_id\": \"daded54f-72c7-4f8e-9d18-9b0abdd9f190\" } ] }","handlingStrategy":"type-guard","validationCode":"function asFileMappingArray(v: unknown): object[] {\n  if (!Array.isArray(v)) throw new Error('value must be array')\n  if (v.length > 0 && (typeof v[0] !== 'object' || v[0] === null || Array.isArray(v[0]))) {\n    throw new Error('array elements must be file mapping objects')\n  }\n  return v as object[]\n}","typeGuard":"function isFileMappingArray(v: unknown): v is object[] {\n  return Array.isArray(v) && (v.length === 0 || (typeof v[0] === 'object' && v[0] !== null && !Array.isArray(v[0])))\n}","tryCatchPattern":"try {\n  await patch(...)\n} catch (e) {\n  if (e.code === 'invalid_param' && /expected dict for files\\[0\\]/.test(e.message)) {\n    // map each element id -> mapping object, retry once\n  } else throw e\n}","preventionTips":["Map every selected file id to its full mapping object before sending.","Reject arrays whose first element is not a plain object.","Run `value.every(v => v && typeof v === 'object')` client-side."],"tags":["rag-pipeline","validation","file-upload","api","rest"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}