{"record":{"id":"fc23f5aa3ee9cafe","repo":"langgenius/dify","slug":"no-file","errorCode":"no_file","errorMessage":"no skill file uploaded","messagePattern":"no skill file uploaded","errorType":"error_code","errorClass":"AgentConfigServiceError","httpStatus":400,"severity":"warning","filePath":"api/controllers/console/app/agent_config_inspector.py","lineNumber":462,"sourceCode":"        config_version_id=target.version_id,\n        config_version_kind=target.version_kind,\n        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    *,","sourceCodeStart":444,"sourceCodeEnd":480,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/app/agent_config_inspector.py#L444-L480","documentation":"Raised as AgentConfigServiceError (code=no_file, HTTP 400) from _read_single_upload: the multipart form-data contained no field named 'file'. The skill-upload endpoint requires exactly one file attachment under that key; absence is treated as a client error, not a missing resource.","triggerScenarios":"POSTing to the agent-config skill upload endpoint with an empty form, a JSON body instead of multipart, or a file under a different field name (e.g. 'upload', 'document', 'skill').","commonSituations":"Client using the wrong field name; sending JSON instead of multipart/form-data; a frontend upload component that attaches the file under a custom key; proxy that strips the file part.","solutions":["Send the file as multipart/form-data under the field name 'file'.","Confirm Content-Type is multipart/form-data;boundary=... and the part name is exactly 'file'.","If the client uses a helper (e.g. FormData), append the file under the key 'file'.","Verify no front proxy/load balancer is dropping the file part."],"exampleFix":"// before\nconst fd = new FormData(); fd.append('upload', blob);\n// after\nconst fd = new FormData(); fd.append('file', blob);","handlingStrategy":"validation","validationCode":"def ensure_single_file_part(request) -> None:\n    if 'file' not in request.files:\n        raise ValueError('multipart form must include a file part named \"file\"')","typeGuard":null,"tryCatchPattern":"from services.errors.agent_config import AgentConfigServiceError\n\ntry:\n    resp = client.post(upload_url, files={'file': blob})\nexcept AgentConfigServiceError as exc:\n    if exc.code == 'no_file':\n        resp = client.post(upload_url, files={'file': blob}, headers={'Content-Type': 'multipart/form-data'})\n    raise","preventionTips":["Use multipart/form-data with a part named exactly 'file'.","Centralize skill-upload construction in one client helper that always appends 'file'.","Verify the proxy/gateway preserves the file part."],"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"}