langgenius/dify · error · ValueError

Both doc_type and doc_metadata must be provided.

Error message

Both doc_type and doc_metadata must be provided.

What it means

Raised in the metadata PUT handler when doc_type or doc_metadata is None (datasets_document.py:1308). Because ValueError is not a BaseHTTPException, it escapes as an HTTP 500 rather than a clean 400 - this is a controller defect. DocumentMetadataUpdatePayload declares both fields optional (str | None and Any = None), so the route accepts the partial body and fails post-parse.

Source

Thrown at api/controllers/console/datasets/datasets_document.py:1309

        session: Session,
        current_tenant_id: str,
        current_user: Account,
        dataset_id: UUID,
        document_id: UUID,
    ):
        dataset_id_str = str(dataset_id)
        document_id_str = str(document_id)
        document = self.get_document(session, dataset_id_str, document_id_str, current_user, current_tenant_id)

        doc_type = req_data.doc_type
        doc_metadata = req_data.doc_metadata

        # The role of the current user in the ta table must be admin, owner, dataset_operator, or editor
        if not current_user.is_dataset_editor:
            raise Forbidden()

        if doc_type is None or doc_metadata is None:
            raise ValueError("Both doc_type and doc_metadata must be provided.")

        if doc_type not in DocumentService.DOCUMENT_METADATA_SCHEMA:
            raise ValueError("Invalid doc_type.")

        if not isinstance(doc_metadata, dict):
            raise ValueError("doc_metadata must be a dictionary.")
        metadata_schema: dict[str, Any] = cast(dict[str, Any], DocumentService.DOCUMENT_METADATA_SCHEMA[doc_type])

        document.doc_metadata = {}
        if doc_type == "others":
            document.doc_metadata = doc_metadata
        else:
            for key, value_type in metadata_schema.items():
                value = doc_metadata.get(key)
                if value is not None and isinstance(value, value_type):
                    document.doc_metadata[key] = value

        document.doc_type = doc_type

View on GitHub (pinned to ef8544b173)

Solutions

  1. Include both doc_type and doc_metadata in the request body.
  2. Server-side fix: make DocumentMetadataUpdatePayload require both fields, or raise InvalidMetadataError instead of ValueError to return a proper 400.

Example fix

# before
if doc_type is None or doc_metadata is None:
    raise ValueError("Both doc_type and doc_metadata must be provided.")
# after
if doc_type is None or doc_metadata is None:
    raise InvalidMetadataError("Both doc_type and doc_metadata must be provided.")
# and make the payload require both fields:
class DocumentMetadataUpdatePayload(BaseModel):
    doc_type: str
    doc_metadata: dict[str, Any]
Defensive patterns

Strategy: validation

Validate before calling

# Validate payload before sending: both fields required
payload = {"doc_type": doc_type, "doc_metadata": doc_metadata}
if payload["doc_type"] is None or payload["doc_metadata"] is None:
    raise ValueError("Both doc_type and doc_metadata must be provided in the request body.")

Type guard

def is_complete_metadata_payload(doc_type, doc_metadata) -> bool:
    return doc_type is not None and doc_metadata is not None

Try / catch

try:
    console.update_document_metadata(dataset_id, document_id, payload)
except HTTPError as e:
    if e.response.status_code >= 500:
        # ValueError currently surfaces as 500; validate payload and retry
        ensure_both_fields(payload)
    else:
        raise

Prevention

When it happens

Trigger: PUT .../documents/{id}/metadata with body {} , {"doc_type":"book"} (missing doc_metadata), or {"doc_metadata":{...}} (missing doc_type); the None-check at line 1308 raises ValueError.

Common situations: Frontend sending a partial update intending patch semantics on a PUT; SDK generated from the optional schema sending only one field; client assuming the server applies defaults.

Related errors


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