VectifyAI/PageIndex · error · ValueError
Invalid doc_id: {doc_id!r}
Error message
Invalid doc_id: {doc_id!r} What it means
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.
Source
Thrown at pageindex/local_store.py:118
pre-existing best-effort behavior stays."""
try:
import fcntl
except ImportError:
yield
return
self._root.mkdir(parents=True, exist_ok=True)
with open(self._root / ".lock", "w") as handle:
fcntl.flock(handle, fcntl.LOCK_EX)
try:
yield
finally:
fcntl.flock(handle, fcntl.LOCK_UN)
# ── documents ──
def save_document(self, doc_id: str, meta: dict, tree: list, pages: list) -> None:
doc_dir = self._doc_dir(doc_id)
if doc_dir is None:
raise ValueError(f"Invalid doc_id: {doc_id!r}")
doc_dir.mkdir(parents=True, exist_ok=True)
_write_json_atomic(doc_dir / "tree.json", tree)
_write_json_atomic(doc_dir / "pages.json", pages)
_write_json_atomic(doc_dir / "doc.json", meta)
manifest = self._read_manifest()
manifest[doc_id] = meta
self._write_manifest(manifest)
def _read_doc_file(self, doc_id: str, name: str):
doc_dir = self._doc_dir(doc_id)
if doc_dir is None or not (doc_dir / "doc.json").is_file():
return None
return _read_json(doc_dir / name)
def get_meta(self, doc_id: str) -> dict | None:
doc_dir = self._doc_dir(doc_id)
if doc_dir is None or not (doc_dir / "doc.json").is_file():
return NoneView on GitHub (pinned to afb5e11976)
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
Example fix
# before client.submit_document(doc_id=user_filename, ...) # e.g. '../etc/passwd' # after import uuid client.submit_document(doc_id=uuid.uuid4().hex, ...)
Defensive patterns
Strategy: validation
Validate before calling
import re, uuid
SAFE = re.compile(r'^[A-Za-z0-9_-]{1,128}$')
doc_id = doc_id if SAFE.match(str(doc_id or '')) else uuid.uuid4().hex Type guard
def is_safe_doc_id(v) -> bool:
import re
return isinstance(v, str) and bool(re.fullmatch(r'[A-Za-z0-9_-]{1,128}', v)) Try / catch
try:
client.submit_document(doc_id, ...)
except ValueError as e:
if 'Invalid doc_id' in str(e):
doc_id = uuid.uuid4().hex
client.submit_document(doc_id, ...) Prevention
- Generate ids yourself (uuid4().hex)
- Never pass raw user filenames as doc_id
- Validate ids at the API boundary
When it happens
Trigger: 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.
Common situations: Generating doc_ids from un-sanitized user input or filenames; passing an int id instead of str; empty string slipping through an upload form.
Related errors
- limit must be between 1 and 100
- offset must be non-negative
- doc_id must be a string or a list of strings.
- system message content must be a string or a list of text pa
- messages must be a non-empty list.
AI-assisted analysis of VectifyAI/PageIndex@afb5e11976 (2026-08-27).
Data as JSON: /api/errors/0fb2ea6c7a6c4bc6.
Report an issue: GitHub.