Skip to content

merge-graphs: unhandled NetworkXError on mixed directed/multigraph inputs, and exit code 0 on crash #1606

Description

@AdrianRusan

Summary

graphify merge-graphs crashes with an unhandled networkx.NetworkXError when the input graphs mix graph types (directed vs undirected, or multigraph: true vs false). On top of the crash, the CLI exits with code 0, so scripts and CI cannot detect the failure.

Environment

  • graphifyy 0.8.35 (PyPI, installed via uv tool install "graphifyy[mcp,ollama]")
  • Python 3.11, macOS (Darwin 25.5)

Reproduction

printf '{"directed": true,  "multigraph": false, "graph": {}, "nodes": [{"id": "x"}], "links": []}' > g1.json
printf '{"directed": false, "multigraph": false, "graph": {}, "nodes": [{"id": "y"}], "links": []}' > g2.json
graphify merge-graphs g1.json g2.json --out merged.json
echo "exit=$?"

Output (abridged):

  File ".../networkx/algorithms/operators/all.py", line 217, in compose_all
    raise nx.NetworkXError("All graphs must be directed or undirected.")
networkx.exception.NetworkXError: All graphs must be directed or undirected.
exit=0

With "multigraph": true in one input instead, the sibling error fires:

  File ".../networkx/algorithms/operators/all.py", line 219, in compose_all
    raise nx.NetworkXError("All graphs must be graphs or multigraphs.")
networkx.exception.NetworkXError: All graphs must be graphs or multigraphs.
exit=0

This bites in practice because per-repo graphify-out/graph.json files produced at different times / by different extract paths don't always agree on the directed/multigraph flags, so a cross-repo merge of otherwise-valid graphs dies mid-pipeline.

Expected behavior

  1. Normalize graph types before nx.compose_all — e.g. upcast every input to the most general type among them (MultiDiGraph covers all), or convert to a canonical type — OR fail fast with a clear message naming the offending file and its flags.
  2. Non-zero exit code on any error. Related: graphify global add also swallows failures with exit 0 (error: 'nodes' for {} input, error: 'list' object has no attribute 'get' for a top-level JSON array), which makes these paths unscriptable.

Happy to test a fix — the repro above is self-contained.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions