{"record":{"id":"be899e777aa1a848","repo":"Graphify-Labs/graphify","slug":"extraction-json-has-len-errors-error-s","errorCode":null,"errorMessage":"Extraction JSON has {len(errors)} error(s):\n","messagePattern":"Extraction JSON has (.+?) error\\(s\\):\n","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"graphify/validate.py","lineNumber":95,"sourceCode":"                try:\n                    unmatched = bool(node_ids) and val not in node_ids\n                except TypeError:\n                    errors.append(\n                        f\"Edge {i} {endpoint} {val!r} is non-hashable - must be a string\"\n                    )\n                    continue\n                if unmatched:\n                    errors.append(f\"Edge {i} {endpoint} '{val}' does not match any node id\")\n\n    return errors\n\n\ndef assert_valid(data: dict) -> None:\n    \"\"\"Raise ValueError with all errors if extraction is invalid.\"\"\"\n    errors = validate_extraction(data)\n    if errors:\n        msg = f\"Extraction JSON has {len(errors)} error(s):\\n\" + \"\\n\".join(f\"  • {e}\" for e in errors)\n        raise ValueError(msg)\n","sourceCodeStart":77,"sourceCodeEnd":96,"githubUrl":"https://github.com/Graphify-Labs/graphify/blob/7fe58b0b0f3873be9a21c30106b8b8527c353aa6/graphify/validate.py#L77-L96","documentation":"Raised by assert_valid (graphify/validate.py) after validate_extraction collected one or more schema violations in an extraction JSON dict: missing 'nodes'/'edges' keys, non-list values, nodes/edges that are not objects, missing required fields (id, label, file_type, source_file on nodes; source, target, relation, confidence, source_file on edges), invalid file_type/confidence enums, non-hashable ids, or edge endpoints that reference no known node id. The single ValueError aggregates every problem as a bulleted list, so one raise reports all defects at once.","triggerScenarios":"Calling assert_valid(data) on LLM-produced or hand-written extraction JSON that violates the schema — typical cases: edge source/target ids that don't match any node id, a node missing 'label', file_type 'snippet' outside {code, document, paper, image, rationale, concept}, or confidence 'high' outside {EXTRACTED, INFERRED, AMBIGUOUS}. Also 'edges' spelled as neither edges nor links (links is accepted as a NetworkX <=3.1 fallback).","commonSituations":"Prompting an LLM to emit graphify extraction JSON and getting drifted field names or hallucinated edge ids; merging partial extractions where a node was dropped but its edges remained; schema drift between graphify versions; hand-editing graph.json and forgetting required fields.","solutions":["Read the bulleted lines in the message — each names the index and the exact defect; fix them in the JSON before re-validating.","For unmatched edge endpoints, either add the missing nodes or drop/repair the dangling edges (most common failure).","Constrain your LLM prompt to the enums: file_type in {code, document, paper, image, rationale, concept}, confidence in {EXTRACTED, INFERRED, AMBIGUOUS}.","Run validate_extraction(data) (returns a list, no raise) in a pre-commit or pipeline step so drift is caught before assert_valid."],"exampleFix":"# before (edge references a node that doesn't exist)\ndata = {\"nodes\": [{\"id\": \"n1\", \"label\": \"A\", \"file_type\": \"code\", \"source_file\": \"a.py\"}],\n         \"edges\": [{\"source\": \"n1\", \"target\": \"nX\", \"relation\": \"calls\", \"confidence\": \"EXTRACTED\", \"source_file\": \"a.py\"}]}\nassert_valid(data)  # ValueError: 1 error(s)\n\n# after\ndata[\"edges\"][0][\"target\"] = \"n1\"\nassert_valid(data)  # passes","handlingStrategy":"validation","validationCode":"from graphify.validate import validate_extraction\n\nerrors = validate_extraction(data)  # returns list[str], never raises\nif errors:\n    data = repair_extraction(data, errors)  # add missing nodes, coerce enums, etc.\nassert not validate_extraction(data)","typeGuard":"def is_valid_extraction(data: object) -> bool:\n    return isinstance(data, dict) and validate_extraction(data) == []","tryCatchPattern":"try:\n    assert_valid(data)\nexcept ValueError as e:\n    # message aggregates every defect as '  • ...' lines — parse and report all\n    defects = [ln.strip(\"• \") for ln in str(e).splitlines() if ln.strip().startswith(\"•\")]\n    report_to_user(defects)  # fix-and-retry loop instead of failing on the first","preventionTips":["Run validate_extraction (non-raising) in pipelines before assert_valid.","Give LLM extractors the exact enums for file_type and confidence in the prompt.","Validate node ids first, then re-point or drop dangling edges referencing unknown ids.","Treat any drift between extraction and schema as a prompt bug, not a data lottery."],"tags":["validation","json","graph","schema"],"backgroundTag":null,"analyzedSha":"7fe58b0b0f3873be9a21c30106b8b8527c353aa6","analyzedAt":"2026-08-14T19:23:21.323Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}