mem0ai/mem0 · critical · ValueError

Failed to load FAISS docstore: potentially malicious pickle

Error message

Failed to load FAISS docstore: potentially malicious pickle file. {e}

What it means

Raised when the legacy pickle docstore fails to unpickle with pickle.UnpicklingError — mem0 treats this as a potential pickle-bomb and aborts with a security ValueError instead of executing arbitrary pickle opcodes. This is deliberate: pickles can execute code on load, so failures are escalated loudly.

Source

Thrown at mem0/vector_stores/faiss.py:221

                # This prevents arbitrary code execution from malicious pickle files
                logger.warning(
                    f"Loading legacy pickle docstore from {docstore_path}. "
                    f"Consider migrating to JSON format for better security."
                )
                data = _safe_pickle_load(docstore_path)
                self.docstore, self.index_to_id = _validate_docstore_structure(data)
                logger.info(f"Loaded FAISS index from {index_path} with {self.index.ntotal} vectors (pickle format)")

                # Auto-migrate to JSON format
                self._save()
                logger.info(f"Migrated docstore to JSON format: {json_docstore_path}")

            else:
                raise FileNotFoundError(f"No docstore found at {docstore_path} or {json_docstore_path}")

        except pickle.UnpicklingError as e:
            logger.error(f"Security error loading FAISS docstore: {e}")
            raise ValueError(f"Failed to load FAISS docstore: potentially malicious pickle file. {e}") from e
        except Exception as e:
            logger.warning(f"Failed to load FAISS index: {e}")
            self.docstore = {}
            self.index_to_id = {}

    def _save(self):
        """Save FAISS index and docstore to disk using JSON format (secure)."""
        if not self.path or not self.index:
            return

        try:
            os.makedirs(self.path, exist_ok=True)
            index_path = f"{self.path}/{self.collection_name}.faiss"
            json_docstore_path = f"{self.path}/{self.collection_name}.json"

            faiss.write_index(self.index, index_path)

            # Save docstore as JSON (safe format, no code execution risk)

View on GitHub (pinned to 001c235229)

Solutions

  1. Do not load the file; treat it as untrusted and source a clean copy from a trusted backup
  2. If you control the origin, regenerate the docstore and let mem0 save in JSON format (auto-migration happens after a successful pickle load)
  3. Delete the legacy pickle and rebuild the store so only the secure JSON format is used going forward

Example fix

# before
# untrusted faiss.docstore left in the directory
vs = FAISS(config)  # ValueError: potentially malicious pickle file

# after
import os
for f in ('faiss.docstore',):
    p = os.path.join(config.path, f)
    if os.path.exists(p):
        os.remove(p)  # force clean rebuild; or restore from trusted backup
Defensive patterns

Strategy: try-catch

Try / catch

try:
    vs = FAISS(config)
except ValueError as e:
    if 'potentially malicious pickle' in str(e):
        # quarantine the file, alert security, rebuild from trusted source
        raise

Prevention

When it happens

Trigger: Loading a faiss.docstore pickle that is malformed, truncated, or crafted; also raised when a non-pickle file (renamed JSON or text) sits at the pickle path and raises UnpicklingError inside _safe_pickle_load.

Common situations: Downloading a docstore from an untrusted source; file corruption in transit or from a partial write; tampering detection; transferring files between Python versions with incompatible pickle protocols.

Related errors


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/faadfda59e676e48. Report an issue: GitHub.