Calling dify workflow api with uploaded file reports {"code": "invalid_param", "message": "XX in input form must be a file", "status": 400} #21047

Closed
opened 2026-02-21 20:10:25 -05:00 by yindo · 1 comment
Owner

Originally created by @weishen on GitHub (Dec 15, 2025).

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

1.7.0

Cloud or Self Hosted

Self Hosted (Docker)

Steps to reproduce

1 setup a workflow that accepts a file param
2 call the workflow api with python as the example says

import requests
import json

def upload_file(file_path, user):
....
def run_workflow(file_id, user, response_mode="blocking"):
    workflow_url = "https://api.dify.ai/v1/workflows/run"
    headers = {
        "Authorization": "Bearer app-xxxxxxxxx",
        "Content-Type": "application/json"
    }

    data = {
        "inputs": {
            "orig_mail": [{
                "transfer_method": "local_file",
                "upload_file_id": file_id,
                "type": "document"
            }]
        },
        "response_mode": response_mode,
        "user": user
    }

    try:
        response = requests.post(workflow_url, headers=headers, json=data)
        if response.status_code == 200:

            return response.json()
        else:

            return {"status": "error", "message": f"Failed to execute workflow, status code: {response.status_code}"}
    except Exception as e:

        return {"status": "error", "message": str(e)}


file_path = "{your_file_path}"
user = "difyuser"


file_id = upload_file(file_path, user)
if file_id:

    result = run_workflow(file_id, user)
    print(result)
else:
    print("upload failed")

✔️ Expected Behavior

the workflow should function normally

Actual Behavior

return error: {"code": "invalid_param", "message": "XX in input form must be a file", "status": 400}

Originally created by @weishen on GitHub (Dec 15, 2025). ### Self Checks - [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542). - [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general). - [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. - [x] I confirm that I am using English to submit this report, otherwise it will be closed. - [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :) - [x] Please do not modify this template :) and fill in all the required fields. ### Dify version 1.7.0 ### Cloud or Self Hosted Self Hosted (Docker) ### Steps to reproduce 1 setup a workflow that accepts a file param 2 call the workflow api with python as the example says ``` import requests import json def upload_file(file_path, user): .... def run_workflow(file_id, user, response_mode="blocking"): workflow_url = "https://api.dify.ai/v1/workflows/run" headers = { "Authorization": "Bearer app-xxxxxxxxx", "Content-Type": "application/json" } data = { "inputs": { "orig_mail": [{ "transfer_method": "local_file", "upload_file_id": file_id, "type": "document" }] }, "response_mode": response_mode, "user": user } try: response = requests.post(workflow_url, headers=headers, json=data) if response.status_code == 200: return response.json() else: return {"status": "error", "message": f"Failed to execute workflow, status code: {response.status_code}"} except Exception as e: return {"status": "error", "message": str(e)} file_path = "{your_file_path}" user = "difyuser" file_id = upload_file(file_path, user) if file_id: result = run_workflow(file_id, user) print(result) else: print("upload failed") ``` ### ✔️ Expected Behavior the workflow should function normally ### ❌ Actual Behavior return error: {"code": "invalid_param", "message": "XX in input form must be a file", "status": 400}
yindo added the 🐞 bugoutdated labels 2026-02-21 20:10:25 -05:00
yindo closed this issue 2026-02-21 20:10:25 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Dec 15, 2025):

Hi @weishen! I'm Dosu and I’m helping the dify team.

The error happens because the workflow API expects file parameters to be passed in the top-level "files" list, not inside the "inputs" dictionary. Your current payload puts the file mapping under "inputs", which triggers the validation error "XX in input form must be a file".

To fix this, after uploading your file and getting the file ID, structure your API call like this:

data = {
    "inputs": {
        # other non-file inputs here if needed
    },
    "files": [
        {
            "variable": "orig_mail",  # must match your workflow variable name
            "transfer_method": "local_file",
            "upload_file_id": file_id,
            "type": "document"
        }
    ],
    "response_mode": response_mode,
    "user": user
}

Make sure:

  • The workflow variable is configured as a File or Array[File] type.
  • The file ID is valid and belongs to the correct tenant.
  • All required fields ("transfer_method", "upload_file_id", "type") are present in the file mapping.

If your workflow expects an array of files, the value for that variable should be a list of file mappings in the "files" array. If it's a single file, just one mapping is enough. This structure matches what the backend expects and should resolve the error "The workflow run API endpoint expects a JSON body with 'inputs' as a required dictionary and 'files' as an optional list; file parameters are expected to be passed in the 'files' list, not embedded inside 'inputs'".

If you still see the error, double-check your workflow variable type and that the file ID is correct and accessible.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Dec 15, 2025): <!-- Greeting --> Hi @weishen! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the dify team. <!-- Answer --> The error happens because the workflow API expects file parameters to be passed in the top-level "files" list, not inside the "inputs" dictionary. Your current payload puts the file mapping under "inputs", which triggers the validation error ["XX in input form must be a file"](https://github.com/langgenius/dify/blob/80c74cf725aeb6055b4eb03aabacf82aaec907a3/api/core/app/apps/base_app_generator.py#L43-L160). To fix this, after uploading your file and getting the file ID, structure your API call like this: ```python data = { "inputs": { # other non-file inputs here if needed }, "files": [ { "variable": "orig_mail", # must match your workflow variable name "transfer_method": "local_file", "upload_file_id": file_id, "type": "document" } ], "response_mode": response_mode, "user": user } ``` Make sure: - The workflow variable is configured as a File or Array[File] type. - The file ID is valid and belongs to the correct tenant. - All required fields ("transfer_method", "upload_file_id", "type") are present in the file mapping. If your workflow expects an array of files, the value for that variable should be a list of file mappings in the "files" array. If it's a single file, just one mapping is enough. This structure matches what the backend expects and should resolve the error ["The workflow run API endpoint expects a JSON body with 'inputs' as a required dictionary and 'files' as an optional list; file parameters are expected to be passed in the 'files' list, not embedded inside 'inputs'"](https://github.com/langgenius/dify/blob/80c74cf725aeb6055b4eb03aabacf82aaec907a3/api/controllers/web/workflow.py#L57-L71). If you still see the error, double-check your workflow variable type and that the file ID is correct and accessible. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/453854ff-a050-45db-a2c0-4885a24539da?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/453854ff-a050-45db-a2c0-4885a24539da?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/453854ff-a050-45db-a2c0-4885a24539da?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/453854ff-a050-45db-a2c0-4885a24539da?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/453854ff-a050-45db-a2c0-4885a24539da?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/453854ff-a050-45db-a2c0-4885a24539da?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/453854ff-a050-45db-a2c0-4885a24539da?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/6088a4f4-073a-43f3-b3d4-4f06fb0c05a0/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=The%20error%20happens%20because%20the%20workflow%20API%20expects%20file%20parameters%20to%20be%20passed%20in%20the%20top-level%20%22files%22%20list%2C%20not%20inside%20the%20%22inputs%22%20dictionary.%20Your%20current%20payload%20puts%20the%20file%20mapping%20under%20%22inputs%22%2C%20which%20triggers%20the%20validation%20error%20%5B%22XX%20in%20input%20form%20must%20be%20a%20file%22%5D%28https%3A//github.com/langgenius/dify/blob/80c74cf725aeb6055b4eb03aabacf82aaec907a3/api/core/app/apps/base_app_generator.py%23L43-L160%29.%0A%0ATo%20fix%20this%2C%20after%20uploading%20your%20file%20and%20getting%20the%20file%20ID%2C%20structure%20your%20API%20call%20like%20this%3A%0A%0A%60%60%60python%0Adata%20%3D%20%7B%0A%20%20%20%20%22inputs%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%23%20other%20non-file%20inputs%20here%20if%20needed%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22files%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22variable%22%3A%20%22orig_mail%22%2C%20%20%23%20must%20match%20your%20workflow%20variable%20name%0A%20%20%20%20%20%20%20%20%20%20%20%20%22transfer_method%22%3A%20%22local_file%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22upload_file_id%22%3A%20file_id%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%20%22document%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%2C%0A%20%20%20%20%22response_mode%22%3A%20response_mode%2C%0A%20%20%20%20%22user%22%3A%20user%0A%7D%0A%60%60%60%0A%0AMake%20sure%3A%0A-%20The%20workflow%20variable%20is%20configured%20as%20a%20File%20or%20Array%5BFile%5D%20type.%0A-%20The%20file%20ID%20is%20valid%20and%20belongs%20to%20the%20correct%20tenant.%0A-%20All%20required%20fields%20%28%22transfer_method%22%2C%20%22upload_file_id%22%2C%20%22type%22%29%20are%20present%20in%20the%20file%20mapping.%0A%0AIf%20your%20workflow%20expects%20an%20array%20of%20files%2C%20the%20value%20for%20that%20variable%20should%20be%20a%20list%20of%20file%20mappings%20in%20the%20%22files%22%20array.%20If%20it%27s%20a%20single%20file%2C%20just%20one%20mapping%20is%20enough.%20This%20structure%20matches%20what%20the%20backend%20expects%20and%20should%20resolve%20the%20error%20%5B%22The%20workflow%20run%20API%20endpoint%20expects%20a%20JSON%20body%20with%20%27inputs%27%20as%20a%20required%20dictionary%20and%20%27files%27%20as%20an%20optional%20list%3B%20file%20parameters%20are%20expected%20to%20be%20passed%20in%20the%20%27files%27%20list%2C%20not%20embedded%20inside%20%27inputs%27%22%5D%28https%3A//github.com/langgenius/dify/blob/80c74cf725aeb6055b4eb03aabacf82aaec907a3/api/controllers/web/workflow.py%23L57-L71%29.%0A%0AIf%20you%20still%20see%20the%20error%2C%20double-check%20your%20workflow%20variable%20type%20and%20that%20the%20file%20ID%20is%20correct%20and%20accessible.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify/issues/29665)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#21047