Multimodal Knowledge Base Support#
Dify knowledge bases can store images as UploadFile records bound to document segments via SegmentAttachmentBinding. When a segment carries image attachments, the image bytes are embedded as multimodal vectors (via vector.create_multimodal()) so that image-to-image retrieval can find the owning segment. This pipeline has two distinct known failure modes β one an access control bug (now fixed), one an indexing bug (open as of this writing).
Bug 1: Invalid upload file in Published Apps (Fixed in v1.15 / PRs #36175, #36195)#
What happened#
Knowledge-indexed images are stored as UploadFile records owned by the account user who performed indexing. When an end-user invokes a published app, file access control sets requires_user_ownership = True on the FileAccessScope, filtering UploadFile rows to those created by that specific end-user. Images from the knowledge base don't pass this filter, returning None from the database lookup and raising Invalid upload file.
This only reproduced in the published app β Studio Preview runs as the account user whose requires_user_ownership is False, so access succeeds.
Fix#
PRs #36175 and #36195 (merged May 2026) introduced an execution-local grant mechanism in api/core/app/file_access/scope.py:
grant_retriever_segment_access(segment_ids)β called during knowledge retrieval to allowlist segment IDs for the current execution.grant_upload_file_access(upload_file_ids)β called when attachment bindings are resolved, adding file IDs to agranted_upload_file_idsfrozenset.
The DatabaseFileAccessController.apply_upload_file_filters() then OR-expands the ownership filter with UploadFile.id IN (granted_ids), allowing end-users to access knowledge-retrieved files without relaxing the per-user filter globally.
Grant call sites:
| Location | What is granted |
|---|---|
dataset_retrieval.py L332 | Segment IDs from retrieval results |
dataset_retrieval.py L525 | Upload file IDs from segment attachment bindings |
retrieval_service.py L923, L969 | Upload file IDs for attachment bindings |
node_runtime.py L379 | Upload file IDs before attachment loader returns File refs |
Upgrade path: Fix is present in v1.15.0 and later. Users on v1.14.x will see the error and should upgrade.
Residual behavior noted post-fix: At least one user reported that after upgrading to v1.15.0 the error was gone but LLM vision did not use the images from the knowledge base in the published app (working correctly in Preview). This may indicate a separate rendering or model configuration issue rather than the access control bug.
Bug 2: Segment Attachment Images Indexed as Text (Issue #38079)#
What happens#
When images are attached to an existing segment via the segment update API (PATCH /console/api/datasets/{dataset_id}/documents/{document_id}/segments/{segment_id} with attachment_ids), VectorService.update_multimodel_vector() creates a Document with page_content=upload_file.name and was calling the wrong vector path.
The root cause: page_content was set to the filename string and the method called vector.add_texts(...) (text embedding path) instead of vector.create_multimodal(...) (multimodal image embedding path).
The SegmentAttachmentBinding row is created correctly, so the database association exists. However, the vector store contains a text embedding of the filename β not the image bytes β making image-to-image retrieval unreliable for these segments.
Note: The current
mainbranch version ofvector_service.pyalready callsvector.create_multimodal(documents)at line 364 , suggesting this was fixed after the issue was filed on 2026-06-27. If you encounter image-to-image retrieval failures on older deployments, verify the deployedvector_service.pyand check whether the issue's patch has landed in your version.
Key Files for Investigation#
| File | Relevance |
|---|---|
api/core/app/file_access/scope.py | FileAccessScope, grant functions, requires_user_ownership |
api/core/app/file_access/controller.py | SQL filter logic with granted-IDs OR expansion |
api/core/rag/retrieval/dataset_retrieval.py | Grant call sites during knowledge retrieval |
api/services/vector_service.py | update_multimodel_vector() β segment attachment indexing |
api/core/rag/datasource/vdb/vector_factory.py | create_multimodal() β correct multimodal embedding path |
api/core/app/apps/base_app_generator.py | Where FileAccessScope is bound at execution start |
References#
- Discussion #35760 β Original user report:
Invalid upload filein published Advanced Chat app - Discussion #35783 β Detailed root-cause analysis of the ownership check failure
- Issue #38079 β Segment attachment images indexed as text instead of multimodal vectors
- PR #36175 / PR #36195 β The execution-local grant fix
- Knowledge Base: File Access Control β Full
FileAccessScopearchitecture