cognee.validate()
Description
Cross-check the graph and vector stores of a dataset and report where they disagree.validate() answers three questions no other call answers: does every edge still point
at nodes that exist, does every deduplicated node still carry the id its own dedup
contract derives, and is every embeddable node actually present in its vector collection.
The check is read-only β it never writes to any store, so it is safe to run against a
production dataset. It is also backend-agnostic: it is driven entirely through
GraphDBInterface.get_graph_data() and VectorDBInterface.retrieve(), so it works
unmodified against every supported graph and vector backend without adapter-specific
code.
Run it after cognify(), after a large import, or after a
migration β the moments when the graph and the vector index can drift apart.
Parameters
Optional[Union[str, List[str]]]
default:"'main_dataset'"
Dataset name(s) to validate. A single string is treated as a one-element list.
Optional[User]
default:"None"
User context for dataset access. Falls back to the default user.
Only one graph is checked per call:
dataset is resolved to the datasets you have
read permission on, and the first of those determines which graph and vector store
are read. Passing several dataset names does not merge them into a combined report β call
validate() once per dataset instead.Returns
ValidationReport β a Pydantic model with three fields:
status is derived from the severities present, not from issue counts:
- any
error-severity issue βunhealthy - otherwise, any
warning-severity issue βdegraded - no issues at all β
healthy
validate, ValidationReport, ValidationIssue, and ValidationStatus are importable
from the cognee top level; the IssueSeverity and IssueType enums are available from
cognee.api.v1.validate. All three enums (ValidationStatus, IssueSeverity,
IssueType) subclass str, so comparing against plain strings
(report.status == "healthy") works without importing them β but printing a member
shows the enum repr (ValidationStatus.HEALTHY), so use .value when you want the
plain string.
What is checked
orphaned_edge β error
orphaned_edge β error
An edge whose
source or target id is not in the graphβs node set. Traversal that
reaches such an edge hits a dead end, so graph-based search silently loses the
connection.The detail names the edge as source -[relationship]-> target along with the id(s)
that are missing. Typically the result of nodes being removed without their edges;
re-running cognify() for the affected dataset, or deleting and re-ingesting the
source data, rebuilds a consistent edge set.identity_id_mismatch β warning
identity_id_mismatch β warning
A node of a type that declares
identity_fields β Entity and EntityType, both
keyed on name β whose id does not equal the id its own class derives from its
properties via Type.id_for(...).Cogneeβs dedup contract is that two nodes with the same identity value are the same
node because they hash to the same id. A node that reached the graph without going
through that contract (a raw write from an importer or a migration, or a node written
by an older Cognee version) can carry a stale or arbitrary id β which means a second,
correctly-derived node for the same entity can coexist as an undetected duplicate.
Hence a warning rather than an error: nothing is broken yet, but deduplication is no
longer guaranteed for that node.The check is skipped for a node whose identity field is absent from its graph
properties β the id cannot be recomputed, and the node may simply predate the field.
To bring mismatched nodes onto the current scheme, re-cognify the affected datasets
from scratch so their ids are derived by the models.missing_vector_entry β error
missing_vector_entry β error
A node of a type that declares
index_fields β Entity (collection Entity_name)
and DocumentChunk (collection DocumentChunk_text) β with no matching point in its
{type}_{index_field} vector collection.The node exists in the graph but is unreachable by every embedding-based search type,
silently: semantic search cannot surface it and cannot use it to seed graph traversal.
Re-running cognify() for the dataset re-indexes the missing nodes. If an entire node
type reports one issue per node, the collection itself is likely missing or empty
rather than individual points having been lost.identity_fields / index_fields
metadata rather than being hardcoded, so a change to either contract is picked up here
automatically.
Cost and when to run
- No LLM calls and no writes. The cost is entirely database reads.
- The graph is read in full through
get_graph_data(), so time and memory scale with the total number of nodes and edges β not with a sample. There is no sampling or limit parameter. - Vector lookups are one batched
retrieve()per collection (at most two:Entity_nameandDocumentChunk_text), not one call per node. - Because it is read-only, it is safe against production stores β but on a very large
dataset prefer a low-load window, and note that the number of
issuesis unbounded: a badly drifted graph can return one issue per affected node or edge.
cognify() or a bulk import, after applying migrations, as
a pre-flight check in CI, or on a schedule as integrity monitoring.
Examples
Over HTTP
The same check is exposed as a read-only endpoint on the API server:See also
report()β the other read-only diagnostic: what the graph contains, rather than whether it is consistentcognify()β the pipeline that writes the nodes, edges, and vector points this call cross-checks- DataPoints β
identity_fields,index_fields, and theid_for()contract the identity check verifies run_startup_migrations()β apply pending schema migrations; validating afterwards confirms the stores still agree