{"record":{"id":"b20fadb4c9e7562e","repo":"invoke-ai/InvokeAI","slug":"empty-path-segments-not-allowed-in-subfolder-path","errorCode":null,"errorMessage":"Empty path segments not allowed in subfolder path","messagePattern":"Empty path segments not allowed in subfolder path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"invokeai/app/services/image_files/image_files_disk.py","lineNumber":291,"sourceCode":"            raise ValueError(\"Image path outside outputs folder, potential directory traversal detected\")\n\n        return resolved_image_path\n\n    @staticmethod\n    def _validate_subfolder(subfolder: str) -> None:\n        \"\"\"Validates a subfolder path to prevent directory traversal while allowing controlled subdirectories.\"\"\"\n        if not subfolder:\n            return\n        if \"\\\\\" in subfolder:\n            raise ValueError(\"Backslashes not allowed in subfolder path\")\n        if subfolder.startswith(\"/\"):\n            raise ValueError(\"Absolute paths not allowed in subfolder path\")\n        parts = subfolder.split(\"/\")\n        for part in parts:\n            if part == \"..\":\n                raise ValueError(\"Parent directory references not allowed in subfolder path\")\n            if part == \"\":\n                raise ValueError(\"Empty path segments not allowed in subfolder path\")\n\n    def validate_path(self, path: Union[str, Path]) -> bool:\n        \"\"\"Validates the path given for an image or thumbnail.\"\"\"\n        path = path if isinstance(path, Path) else Path(path)\n        return path.exists()\n\n    def get_workflow(self, image_name: str, image_subfolder: str = \"\") -> str | None:\n        image = self.get(image_name, image_subfolder=image_subfolder)\n        workflow = image.info.get(\"invokeai_workflow\", None)\n        if isinstance(workflow, str):\n            return workflow\n        return None\n\n    def get_graph(self, image_name: str, image_subfolder: str = \"\") -> str | None:\n        image = self.get(image_name, image_subfolder=image_subfolder)\n        graph = image.info.get(\"invokeai_graph\", None)\n        if isinstance(graph, str):\n            return graph","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/image_files/image_files_disk.py#L273-L309","documentation":"Empty segments in the subfolder (e.g. 'a//b', 'a/', or leading '/') are rejected to keep paths canonical and avoid ambiguity in storage layout. Raises ValueError('Empty path segments not allowed in subfolder path').","triggerScenarios":"Passing image_subfolder like 'a//b', 'a/', or '' handled after the falsy check (non-empty but with empty segments); joining strings with trailing separators.","commonSituations":"String-concatenating subfolder parts with stray slashes; splitting/rejoining paths from user input; trailing slash from URL parsing.","solutions":["Normalize the subfolder with posixpath.normpath before calling","Filter out empty parts: '/'.join(p for p in sub.split('/') if p)","Reject or strip trailing/leading slashes at your API boundary"],"exampleFix":"// before\nsub = board + '/'  # 'myboard/'\n// after\nsub = '/'.join(p for p in sub.split('/') if p)","handlingStrategy":"validation","validationCode":"import posixpath\ndef canonical_subfolder(s: str) -> str:\n    return posixpath.normpath(s.strip('/'))\nsub = canonical_subfolder(sub)\nassert '' not in sub.split('/')","typeGuard":"def has_no_empty_segments(s: object) -> bool:\n    return isinstance(s, str) and s != '' and all(p for p in s.split('/'))","tryCatchPattern":"try:\n    service.get(name, image_subfolder=subfolder)\nexcept ValueError as e:\n    if 'Empty path segments' in str(e):\n        subfolder = '/'.join(p for p in subfolder.split('/') if p)\n        service.get(name, image_subfolder=subfolder)","preventionTips":["Normalize subfolders with posixpath.normpath before every call","Strip leading/trailing slashes from user input","Avoid hand-concatenating path fragments with '/'"],"tags":["validation","path","normalization"],"backgroundTag":"invalid-path-separator","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}