{"record":{"id":"3f4ee3e527db8220","repo":"langgenius/dify","slug":"too-many-files","errorCode":"too_many_files","errorMessage":"only one skill file is allowed","messagePattern":"only one skill file is allowed","errorType":"error_code","errorClass":"AgentConfigServiceError","httpStatus":400,"severity":"warning","filePath":"api/controllers/console/app/agent_config_inspector.py","lineNumber":464,"sourceCode":"        user_id=target.account_id,\n    )\n\n\ndef _file_list_response(target: _ResolvedConsoleTarget) -> dict[str, object]:\n    return _service().list_files(\n        tenant_id=target.tenant_id,\n        agent_id=target.agent_id,\n        config_version_id=target.version_id,\n        config_version_kind=target.version_kind,\n        user_id=target.account_id,\n    )\n\n\ndef _read_single_upload() -> tuple[bytes, str]:\n    if \"file\" not in request.files:\n        raise AgentConfigServiceError(\"no_file\", \"no skill file uploaded\", status_code=400)\n    if len(request.files) > 1:\n        raise AgentConfigServiceError(\"too_many_files\", \"only one skill file is allowed\", status_code=400)\n    upload = request.files[\"file\"]\n    return upload.stream.read(), upload.filename or \"\"\n\n\ndef _skill_upload_response(target: _ResolvedConsoleTarget) -> tuple[dict[str, object], int]:\n    return _upload_skill_for_target(\n        tenant_id=target.tenant_id,\n        agent_id=target.agent_id,\n        user_id=target.account_id,\n        version_id=target.version_id,\n        version_kind=target.version_kind,\n    )\n\n\ndef _upload_skill_for_target(\n    *,\n    tenant_id: str,\n    agent_id: str,","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/app/agent_config_inspector.py#L446-L482","documentation":"Raised as AgentConfigServiceError (code=too_many_files, HTTP 400) from _read_single_upload: the multipart form-data contained more than one file part. The skill-upload endpoint accepts exactly one file; additional parts are rejected to keep skill processing single-file.","triggerScenarios":"POSTing to the agent-config skill upload endpoint with multiple files under 'file' (repeated parts) or with several parts under different keys that all count toward request.files.","commonSituations":"Client upload component that supports multi-select and submits all selected files in one request; appending the same file twice; a batch helper that wraps a single-file endpoint.","solutions":["Send exactly one file per request; loop on the client to upload additional files.","If multiple files are needed, call the endpoint once per file sequentially or in bounded parallelism.","Trim any accidental extra file parts before submit.","Update the UI to disable multi-select for this endpoint."],"exampleFix":"// before\nfiles.forEach(f => fd.append('file', f));  // many parts\n// after\nfor (const f of files) { await uploadSingle(f); }  // one per request","handlingStrategy":"validation","validationCode":"def ensure_at_most_one_file(request) -> None:\n    if len(request.files) > 1:\n        raise ValueError('upload only one file per request')","typeGuard":null,"tryCatchPattern":"from services.errors.agent_config import AgentConfigServiceError\n\ntry:\n    client.post(upload_url, files=[('file', f) for f in files])\nexcept AgentConfigServiceError as exc:\n    if exc.code == 'too_many_files':\n        for f in files:\n            client.post(upload_url, files={'file': f})\n    raise","preventionTips":["Upload one file per request; loop on the client for batches.","Disable multi-select in the skill-upload UI component.","Do not append extra file parts under alternate keys."],"tags":["upload","multipart","agent-config","skills","validation"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}