langgenius/dify · error

Unsupported Media Type

Error message

Unsupported Media Type

What it means

HTTP 415 Unsupported Media Type from the RAG pipeline draft-workflow sync endpoint. The handler inspects `request.headers["Content-Type"]`: only `application/json` (parsed via `console_ns.payload`) and `text/plain` (parsed via `model_validate_json(request.data)`) are accepted; any other Content-Type triggers `abort(415)` with the default message.

Source

Thrown at api/controllers/console/datasets/rag_pipeline/rag_pipeline_workflow.py:234

    @rbac_permission_required(RBACResourceScope.DATASET, RBACPermission.DATASET_EDIT)
    @console_ns.expect(console_ns.models[DraftWorkflowSyncPayload.__name__])
    @console_ns.response(200, "Success", console_ns.models[RagPipelineWorkflowSyncResponse.__name__])
    def post(self, current_user: Account, pipeline: Pipeline):
        """
        Sync draft workflow
        """
        content_type = request.headers.get("Content-Type", "")

        if "application/json" in content_type:
            payload_dict = console_ns.payload or {}
            payload = DraftWorkflowSyncPayload.model_validate(payload_dict)
        elif "text/plain" in content_type:
            try:
                payload = DraftWorkflowSyncPayload.model_validate_json(request.data)
            except (ValueError, ValidationError):
                return {"message": "Invalid JSON data"}, 400
        else:
            abort(415)
        rag_pipeline_service = RagPipelineService(db.session())

        try:
            environment_variables_list = Workflow.normalize_environment_variable_mappings(
                payload.environment_variables or [],
            )
            environment_variables = [
                variable_factory.build_environment_variable_from_mapping(obj) for obj in environment_variables_list
            ]
            conversation_variables_list = payload.conversation_variables or []
            conversation_variables = [
                variable_factory.build_conversation_variable_from_mapping(obj) for obj in conversation_variables_list
            ]
            workflow = rag_pipeline_service.sync_draft_workflow(
                pipeline=pipeline,
                graph=payload.graph,
                unique_hash=payload.hash,
                account=current_user,

View on GitHub (pinned to ef8544b173)

Solutions

  1. Set `Content-Type: application/json` and send a JSON body matching `DraftWorkflowSyncPayload`.
  2. If streaming a raw JSON string, use `Content-Type: text/plain` and ensure the body is valid JSON parseable by `DraftWorkflowSyncPayload.model_validate_json`.
  3. Do not use `FormData`/`multipart` for this route — it expects a single JSON document.
  4. Verify no intermediary (gateway, SDK) rewrites the Content-Type.

Example fix

// before
fetch(url, { method: 'PUT', body: new FormData(form) })
// after
fetch(url, {
  method: 'PUT',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(payload)
})
Defensive patterns

Strategy: validation

Validate before calling

def ok_content_type(ct: str | None) -> bool:
    ct = (ct or "").lower()
    return "application/json" in ct or "text/plain" in ct

headers = {"Content-Type": "application/json"}
assert ok_content_type(headers["Content-Type"])

Type guard

ALLOWED = ("application/json", "text/plain")
def is_allowed_content_type(ct: str | None) -> bool:
    return any(a in (ct or "").lower() for a in ALLOWED)

Try / catch

try:
    resp = client.put(url, json=payload, headers={"Content-Type": "application/json"})
except HTTPError as err:
    if err.response.status_code == 415:
        # switch to JSON body and retry
        ...
    elif err.response.status_code == 400:
        # text/plain body failed model_validate_json
        ...
    raise

Prevention

When it happens

Trigger: POST/PUT to the draft-workflow sync route with a Content-Type other than `application/json` or `text/plain` — e.g. `multipart/form-data`, `application/x-www-form-urlencoded`, missing Content-Type, or a Content-Type with an unexpected main type.

Common situations: Client using `FormData` instead of JSON; curl/Postman defaulting to `application/x-www-form-urlencoded`; SDK that auto-sets `multipart/form-data` for large payloads; reverse proxy stripping Content-Type.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/fda060df24283c3f. Report an issue: GitHub.