Troubleshooting
On this page
RAGInitializationError on construction
Cause: one of vector_db, llm, chunker, context_manager was None.
Fix: the exception message lists exactly which arguments were missing — supply real objects for all four. See RAGSystem.__init__ Raises.
ValueError: ❌ Rerank weights must sum to 1.0 (got ...)
Cause: the four rerank_*_weight fields on RAGConfig, or RerankerConfig's equivalent fields, don't sum to within [0.99, 1.01].
Fix: adjust the weights so they total 1.0, or use the class defaults (0.40 / 0.40 / 0.10 / 0.10). See Configuration.
Reranker mode silently became "heuristic" even though I asked for "llm"
Cause: you constructed Reranker (directly, or indirectly via RAGSystem(config=RAGConfig(enable_reranking=True, rerank_mode="llm"))) without supplying an llm. Reranker.__init__ downgrades the mode automatically and logs a warning.
Fix: pass a working llm object. For RAGSystem, this is the same llm you already constructed it with — RAGSystem always passes self.llm into the Reranker it builds internally, so this specific scenario should only occur if you construct Reranker directly without an LLM. See Reranker constructor.
remove_document() returns 0 even though the document existed
Cause: RAGSystem.remove_document() catches all exceptions from vector_db.remove_by_doc_id() internally and returns 0 rather than propagating — so a 0 return can mean either "not found" or "an error occurred that was logged but swallowed".
Fix: check your application logs for an ERROR-level message from RAGSystem.remove_document to distinguish the two cases. See remove_document.
Async ingestion (aadd_documents) raises a TypeError I don't get from add_documents
Cause: add_documents() expects List[LoadedDocument]; aadd_documents() expects Dict[str, str] ({doc_id: text}). Passing the wrong shape to either will fail.
Fix: convert between the two shapes explicitly, or standardize on one ingestion path in your application. See the async ingestion warning.
Language detection thresholds differ across modules
Several independent language-detection implementations exist in the codebase, each with a slightly different heuristic:
Symptom: the same input string might be classified as Arabic by one code path and English by another (e.g. a short English sentence containing one Arabic word will be "ar" under the "any character" methods but likely "en" under the ratio-based methods).
Fix: if consistent language classification across the pipeline matters for your use case, detect the language once yourself (pick one method) and pass it explicitly wherever a language parameter is accepted (RAGSystem.generate(..., language=...), PromptRouter.build(..., language=...)), rather than relying on each module's independent auto-detection.
DocumentVersionManager.add_or_update() raises ImportError
Cause: the method internally imports LoadedDocument from zerda.rag.core.rag_system, which only resolves if core is installed within that package namespace. See Architecture.
Fix: install/vendor core as zerda/rag/core/ rather than as a bare top-level core package, or patch the import if you maintain a fork.
rollback() raises ValueError
Cause: original_texts (the dict you pass to rollback()) doesn't contain an entry for the doc_id you're rolling back.
Fix: DocumentVersionManager does not retain full historical text (only hashes and short previews) — you must supply the original text yourself. See rollback.
My retrieval cache never seems to help (hit_rate stays near 0)
Likely causes, in order of likelihood based on the source:
- High query diversity relative to
cache_maxsize— increasecache_maxsize. - Frequent document ingestion clearing the cache — see Cookbook: avoiding cache-clearing storms.
- Using the async path —
aretrieve()never touches the cache at all, by design; only the synchronousretrieve()does. Seearetrieve.