Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[Bug]: `graphify export svg` writes a graph.svg that is not well-formed XML when a label contains a control character

Closed Beginner friendly
#4,241 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

  • #4244 by @Yyunozor — closed without merging

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python

Research direction

In graphify/export.py, inspect to_svg and the existing _strip_xml_illegal usage in to_graphml. Add or extend a regression test alongside the tests for #2897, covering control characters in node labels and the legend. Run the focused export tests; done means SVG output is well-formed XML and the control characters are dropped from the drawn text.

Written by the indexing model from the issue text.

Description

Pre-flight checks
  • I have checked the Troubleshooting section in the README
What happened?

A node or community label that contains a C0 control character (an ANSI escape from a pasted terminal capture, a form feed used as a section separator, a NUL) ends up in graph.svg. XML 1.0 forbids those characters, so the file is not well-formed. graphify export svg still prints graph.svg written and exits 0.

The same graph exports a well-formed graph.graphml. #2897 made to_graphml strip these characters and left to_svg out, for a reason given in #2899: to_svg does not crash, matplotlib only warns about a missing glyph and draws a box. That holds for a label without a pair of $ (between two of them, a control character can make matplotlib read invalid mathtext and to_svg raise ValueError), but the file it writes is not valid XML, and the command reports success.

Expected: a well-formed graph.svg, with the control character dropped from the drawn text, as to_graphml does.

Cause, in graphify/export.py: to_svg hands the raw node labels to nx.draw_networkx_labels and the raw community label to mpatches.Patch. With the default svg.fonttype, matplotlib's SVG backend writes each drawn string into a comment (<!-- text -->). Its comment escaping handles &, <, > and --, not control characters. _strip_xml_illegal is only called from to_graphml.

Steps to reproduce
mkdir svg-repro && cd svg-repro
printf '# Notes\n\n## Build \033[31mlog capture\033[0m\n\nSome text.\n\n## Deploy\n\nSee [[Notes]].\n' > notes.md
printf 'def helper():\n    return 1\n\ndef main():\n    return helper()\n' > app.py
graphify update .
graphify export svg
xmllint --noout graphify-out/graph.svg
graphify export graphml
xmllint --noout graphify-out/graph.graphml

The legend takes the same path. On a project with no control character in any heading, graphify export svg --labels labels.json with {"0": "Core \u001b[0mmodule", "1": "Other\u000cgroup"} gives the same xmllint error (<!-- Core [0mmodule (4) -->).

Error output or graph output
.../graphify/export.py:1409: UserWarning: Glyph 27 () missing from font(s) DejaVu Sans.
  plt.savefig(output_path, format="svg", bbox_inches="tight",
graph.svg written - embeds in Obsidian, Notion, GitHub READMEs
graphify-out/graph.svg:513: parser error : xmlParseComment: invalid xmlChar value 27
     <!-- Build [31mlog capture[0m -->

The parentheses of the warning hold the ESC character. xmllint exits 1 on graph.svg and 0 on graph.graphml. The heading becomes the node Build \x1b[31mlog capture\x1b[0m in graph.json.

Graphify version

0.9.80 (v8 @ 6478eb7)

Operating System

macOS

Python Version

3.12

Installation Method

built from source (git clone)

Additional Environment Details

uv sync --all-extras --frozen, matplotlib 3.10.9 (the uv.lock version); the same file is malformed with matplotlib 3.11.2. AST-only path (graphify update), no API key involved. Reproduced on a clean checkout of v8 at 6478eb7 (no local change).

Additional context

I have a small fix and can open a PR: pass the node labels and the legend text through _strip_xml_illegal in to_svg, with a regression test next to the #2897 tests.

Dominant language
Python
Stars
124k
Forks
11.9k
PR merge metrics
No merged PRs in 30d

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Graphify-Labs/graphify

All issues in Graphify-Labs/graphify

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.