{"record":{"id":"b87e63474528b035","repo":"OpenBMB/ChatDev","slug":"file-sources-must-contain-at-least-one-entry","errorCode":null,"errorMessage":"file_sources must contain at least one entry","messagePattern":"file_sources must contain at least one entry","errorType":"validation","errorClass":"ConfigError","httpStatus":null,"severity":"error","filePath":"entity/configs/node/memory.py","lineNumber":203,"sourceCode":"            required=False,\n            description=\"Optional embedding configuration\",\n            child=EmbeddingConfig,\n        ),\n    }\n\n\n@dataclass\nclass FileMemoryConfig(BaseConfig):\n    index_path: str | None = None\n    file_sources: List[FileSourceConfig] = field(default_factory=list)\n    embedding: EmbeddingConfig | None = None\n\n    @classmethod\n    def from_dict(cls, data: Mapping[str, Any], *, path: str) -> \"FileMemoryConfig\":\n        mapping = require_mapping(data, path)\n        sources_raw = ensure_list(mapping.get(\"file_sources\"))\n        if not sources_raw:\n            raise ConfigError(\"file_sources must contain at least one entry\", extend_path(path, \"file_sources\"))\n        sources: List[FileSourceConfig] = []\n        for idx, item in enumerate(sources_raw):\n            sources.append(FileSourceConfig.from_dict(item, path=extend_path(path, f\"file_sources[{idx}]\")))\n\n        index_path = optional_str(mapping, \"index_path\", path)\n        if index_path is None:\n            index_path = optional_str(mapping, \"memory_path\", path)\n\n        embedding_cfg = None\n        if \"embedding\" in mapping and mapping[\"embedding\"] is not None:\n            embedding_cfg = EmbeddingConfig.from_dict(mapping[\"embedding\"], path=extend_path(path, \"embedding\"))\n\n        return cls(index_path=index_path, file_sources=sources, embedding=embedding_cfg, path=path)\n\n    FIELD_SPECS = {\n        \"index_path\": ConfigFieldSpec(\n            name=\"index_path\",\n            display_name=\"Index Path\",","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/entity/configs/node/memory.py#L185-L221","documentation":"FileMemoryConfig.from_dict requires a non-empty 'file_sources' list (missing key yields None, which ensure_list turns into an empty list and also fails). A file memory with no sources has nothing to index, so it is rejected.","triggerScenarios":"Omitting 'file_sources', passing an empty list [], or passing file_sources: null. Each FileSourceConfig in the list is then validated individually.","commonSituations":"Dynamic config generation where the sources list ends up empty; commenting out all sources for testing; forgetting the key when authoring a memory node.","solutions":["Add at least one file source entry: \"file_sources\": [{\"path\": \"./docs\"}]","If no file memory is wanted, remove the file memory node/config entirely rather than emptying the list","When generating dynamically, skip creating FileMemoryConfig when the sources list is empty"],"exampleFix":"# before\n{\"file_sources\": []}\n# after\n{\"file_sources\": [{\"path\": \"./docs\", \"recursive\": true}]}","handlingStrategy":"validation","validationCode":"sources = cfg.get('file_sources') or []\nif not sources:\n    raise ValueError('file memory requires >=1 source')  # or skip creating the node","typeGuard":"def has_file_sources(cfg: dict) -> bool:\n    s = cfg.get('file_sources')\n    return isinstance(s, list) and len(s) > 0","tryCatchPattern":"try:\n    FileMemoryConfig.from_dict(data, path='fm')\nexcept ConfigError as e:\n    if 'file_sources' in e.path:\n        data['file_sources'] = [{'path': DEFAULT_DOCS_DIR}]\n        FileMemoryConfig.from_dict(data, path='fm')\n    else:\n        raise","preventionTips":["Skip creating file-memory nodes when the sources list is empty","Guard dynamic generation with 'if not sources: return None'","Don't comment out all sources and leave the node in place"],"tags":["config","memory","file","validation","python"],"backgroundTag":"schema-validation-failed","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}