Error Handling Mechanisms in graphviz2drawio: Custom Exceptions and CLI Recovery
graphviz2drawio implements a layered error-handling strategy combining a custom exception hierarchy, defensive validation checks, and user-friendly CLI error reporting to ensure robust GraphViz-to-DrawIO conversion.
The hbmartin/graphviz2drawio library converts GraphViz DOT files into DrawIO-compatible MXGraph format. Understanding the error handling mechanisms in graphviz2drawio is essential for both library consumers integrating the Python API and command-line users processing batch conversions. The codebase employs specific custom exceptions defined in graphviz2drawio/models/Errors.py alongside strategic try/except blocks to manage malformed SVG data, invalid GraphViz output, and encoding issues.
Custom Exception Hierarchy
All conversion-specific errors inherit from the base class GdValueError, defined in graphviz2drawio/models/Errors.py. This design allows callers to catch any graphviz2drawio-specific failure using a single except GdValueError: clause while still permitting granular exception handling.
The library defines six specific exception types for distinct failure modes:
CouldNotParsePathError– Raised when an SVG element contains unparsable path data in itsdattribute (lines 13–19)MissingTitleError– Triggered when a<g>element representing a node, edge, or cluster lacks a required title comment (lines 22–28)MissingTextError– Indicates a text element is missing required attributes (lines 31–37)InvalidBezierParameterError– Occurs when Bézier subdivision receives a parametertoutside the valid range[0, 1](lines 40–45)MissingIdentifiersError– Raised when a node or edge SVG element lacks both anidattribute and a title (lines 47–53)UnableToParseGraphError– Signals thatpygraphviz.AGraph.draw()returnedNone, indicating invalid GraphViz output (lines 56–62)
Defensive Checks and Explicit Raises
Throughout the core conversion pipeline, functions employ defensive programming with explicit raise statements to fail fast and provide specific context about validation failures.
Node and Edge Validation
In graphviz2drawio/mx/NodeFactory.from_svg, the factory validates that both sid (SVG id) and gid (title) are present before creating a node object. If either identifier is missing, it immediately raises MissingIdentifiersError(sid, gid) to guarantee every node has a unique reference.
Similarly, graphviz2drawio/models/SvgParser.parse_nodes_edges_clusters iterates through SVG group elements and ensures each contains a title comment. When a group lacks this required metadata, it raises MissingTitleError(g) to prevent silent data loss during conversion.
Geometric and Graph Validation
The Bézier curve processing in graphviz2drawio/mx/bezier.subdivide validates that the subdivision parameter t falls within the inclusive range [0, 1]. An illegal value triggers InvalidBezierParameterError(t), stopping curve corruption before it propagates to the output geometry.
The main entry point graphviz2drawio/graphviz2drawio.convert verifies that GraphViz successfully generated SVG output. When pygraphviz.AGraph.draw() returns None, the function raises UnableToParseGraphError(graph) to indicate the input DOT file is invalid or GraphViz execution failed.
Path Parsing Protection
When graphviz2drawio/mx/RectFactory.rect_from_svg_path encounters malformed path data, the resulting CouldNotParsePathError(path_d) provides the exact offending path string, enabling precise debugging of SVG generation issues.
Top-Level CLI Error Handling
The command-line interface in graphviz2drawio/__main__.py implements comprehensive error handling to surface user-friendly messages while maintaining diagnostic detail.
Conversion Wrapper
The convert() call is wrapped in a try/except block that handles specific encoding and unexpected failures:
try:
output = convert(to_convert, program)
except UnicodeDecodeError:
# Automatic UTF-8 retry for Windows-specific encoding issues
return _convert_file(...)
except Exception:
_write_stderr_message(str(to_convert))
raise
This structure catches UnicodeDecodeError to implement an automatic fallback to UTF-8 encoding (lines 46–53). For all other exceptions, it invokes _write_stderr_message (lines 24–31) to print a formatted error block containing the Python version, library version, and input file path before re-raising the exception to ensure a non-zero exit status.
Argument Validation
The _validate_args function performs pre-flight checks on command-line arguments, verifying mutually exclusive options like --stdout and --outfile, and confirming required input files exist. Upon validation failure, it prints a clear error message and calls sys.exit(1) (lines 16–23).
Graceful Degradation for Edge Cases
Not all errors halt execution. The utility function adjust_color_opacity in graphviz2drawio/mx/utils.py demonstrates graceful degradation by wrapping hex color parsing in a try/except block:
try:
# Parse and adjust hex color opacity
...
except ValueError:
return hex_string # Return original on parse failure
When a color string cannot be parsed as valid hexadecimal, the function returns the original string rather than crashing, allowing the conversion to continue with potentially malformed but non-critical styling attributes.
Code Examples
Catching Specific Conversion Errors
from graphviz2drawio.models.Errors import MissingTitleError, GdValueError
from graphviz2drawio.graphviz2drawio import convert
from pygraphviz import AGraph
dot = "digraph { a -> b }"
graph = AGraph(string=dot)
try:
mx_xml = convert(graph)
except MissingTitleError as exc:
print(f"Title missing in SVG element: {exc}")
except GdValueError as exc:
print(f"Graph conversion failed: {exc}")
Handling CLI Errors Programmatically
import subprocess
result = subprocess.run(
["graphviz2drawio", "example.dot"],
capture_output=True,
text=True,
)
if result.returncode != 0:
print("Conversion failed:")
print(result.stderr) # Contains formatted error from _write_stderr_message
Validating Bézier Parameters
from graphviz2drawio.mx.bezier import subdivide
from graphviz2drawio.models.Errors import InvalidBezierParameterError
try:
left, right = subdivide(p1, c1, c2, p2, t=1.5)
except InvalidBezierParameterError as exc:
print(f"Invalid curve parameter: {exc}")
Summary
- Custom exception hierarchy centered on
GdValueErroringraphviz2drawio/models/Errors.pyenables both broad and granular error catching - Defensive validation throughout
NodeFactory,SvgParser, andbeziermodules raises specific exceptions likeMissingIdentifiersErrorandInvalidBezierParameterErrorat the point of failure - CLI resilience in
graphviz2drawio/__main__.pyprovides automatic UTF-8 fallback for encoding errors and structured stderr reporting via_write_stderr_message - Graceful degradation in utility functions like
adjust_color_opacityallows conversion to continue despite malformed non-critical data - Pre-flight validation via
_validate_argsensures argument errors are caught before conversion begins with clearsys.exit(1)termination
Frequently Asked Questions
What is the base exception class for all graphviz2drawio errors?
All custom exceptions in graphviz2drawio inherit from GdValueError, defined in graphviz2drawio/models/Errors.py. This base class allows you to catch any conversion-specific error using except GdValueError: while still permitting handlers for specific subclasses like MissingTitleError or UnableToParseGraphError.
How does graphviz2drawio handle file encoding issues?
The CLI entry point in graphviz2drawio/__main__.py specifically catches UnicodeDecodeError and automatically retries the conversion using UTF-8 encoding. This handles Windows-specific encoding issues without requiring user intervention. If the retry fails, the error propagates to the generic exception handler which writes a detailed error message to stderr.
Can I catch all graphviz2drawio conversion errors with a single except clause?
Yes. Since all custom exceptions inherit from GdValueError, you can use a single except GdValueError as exc: clause to catch any conversion-related failure including CouldNotParsePathError, MissingIdentifiersError, and UnableToParseGraphError. This is the recommended approach for library consumers who want to handle all graphviz2drawio-specific errors uniformly.
What happens when GraphViz produces invalid or empty output?
When pygraphviz.AGraph.draw() returns None—indicating GraphViz could not render the graph—the convert() function in graphviz2drawio/graphviz2drawio.py raises UnableToParseGraphError. This provides immediate feedback that the input DOT syntax is invalid or GraphViz installation/configuration is faulty, rather than proceeding with null data.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →