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_typeView on GitHub (pinned to ef8544b173)
Solutions
- Include both doc_type and doc_metadata in the request body.
- 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
- Always include both doc_type and doc_metadata in the PUT body.
- Treat this as a server bug: prefer patching the controller to raise InvalidMetadataError (400).
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
- Invalid doc_type.
- doc_metadata must be a dictionary.
- invalid_metadata
- ${name} must be a non-empty array
- streaming response body missing
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/798938df091747f4.
Report an issue: GitHub.