{"record":{"id":"0fb2ea6c7a6c4bc6","repo":"VectifyAI/PageIndex","slug":"invalid-doc-id-doc-id-r","errorCode":null,"errorMessage":"Invalid doc_id: {doc_id!r}","messagePattern":"Invalid doc_id: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pageindex/local_store.py","lineNumber":118,"sourceCode":"        pre-existing best-effort behavior stays.\"\"\"\n        try:\n            import fcntl\n        except ImportError:\n            yield\n            return\n        self._root.mkdir(parents=True, exist_ok=True)\n        with open(self._root / \".lock\", \"w\") as handle:\n            fcntl.flock(handle, fcntl.LOCK_EX)\n            try:\n                yield\n            finally:\n                fcntl.flock(handle, fcntl.LOCK_UN)\n\n    # ── documents ──\n    def save_document(self, doc_id: str, meta: dict, tree: list, pages: list) -> None:\n        doc_dir = self._doc_dir(doc_id)\n        if doc_dir is None:\n            raise ValueError(f\"Invalid doc_id: {doc_id!r}\")\n        doc_dir.mkdir(parents=True, exist_ok=True)\n        _write_json_atomic(doc_dir / \"tree.json\", tree)\n        _write_json_atomic(doc_dir / \"pages.json\", pages)\n        _write_json_atomic(doc_dir / \"doc.json\", meta)\n        manifest = self._read_manifest()\n        manifest[doc_id] = meta\n        self._write_manifest(manifest)\n\n    def _read_doc_file(self, doc_id: str, name: str):\n        doc_dir = self._doc_dir(doc_id)\n        if doc_dir is None or not (doc_dir / \"doc.json\").is_file():\n            return None\n        return _read_json(doc_dir / name)\n\n    def get_meta(self, doc_id: str) -> dict | None:\n        doc_dir = self._doc_dir(doc_id)\n        if doc_dir is None or not (doc_dir / \"doc.json\").is_file():\n            return None","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/VectifyAI/PageIndex/blob/afb5e119766630af6014b04fe8b53357527bc05e/pageindex/local_store.py#L100-L136","documentation":"save_document() validates doc_id through _doc_dir(); when it returns None the identifier can't be mapped to a safe on-disk directory (empty, wrong type, or containing path-traversal/invalid characters). The ValueError aborts before any files are written or the manifest is touched.","triggerScenarios":"Calling submit_document()/save_document() with doc_id='' , doc_id=None, or values like '../../etc' or names with characters the store refuses — anything for which _doc_dir() yields None.","commonSituations":"Generating doc_ids from un-sanitized user input or filenames; passing an int id instead of str; empty string slipping through an upload form.","solutions":["Use a clean identifier: non-empty string of safe characters (letters, digits, '-', '_') or a uuid4 hex","Sanitize/validate doc_id before calling submit_document","Check _doc_dir()'s accepted pattern and conform to it"],"exampleFix":"# before\nclient.submit_document(doc_id=user_filename, ...)  # e.g. '../etc/passwd'\n# after\nimport uuid\nclient.submit_document(doc_id=uuid.uuid4().hex, ...)","handlingStrategy":"validation","validationCode":"import re, uuid\nSAFE = re.compile(r'^[A-Za-z0-9_-]{1,128}$')\ndoc_id = doc_id if SAFE.match(str(doc_id or '')) else uuid.uuid4().hex","typeGuard":"def is_safe_doc_id(v) -> bool:\n    import re\n    return isinstance(v, str) and bool(re.fullmatch(r'[A-Za-z0-9_-]{1,128}', v))","tryCatchPattern":"try:\n    client.submit_document(doc_id, ...)\nexcept ValueError as e:\n    if 'Invalid doc_id' in str(e):\n        doc_id = uuid.uuid4().hex\n        client.submit_document(doc_id, ...)","preventionTips":["Generate ids yourself (uuid4().hex)","Never pass raw user filenames as doc_id","Validate ids at the API boundary"],"tags":["doc-id","validation","local-store","path-safety"],"backgroundTag":"invalid-identifier","analyzedSha":"afb5e119766630af6014b04fe8b53357527bc05e","analyzedAt":"2026-08-27T11:20:48.519Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}