{"record":{"id":"0317c911cef079ea","repo":"apache/beam","slug":"graphviz-dot-executable-not-available-for-rendering-non-dot","errorCode":null,"errorMessage":"Graphviz dot executable not available for rendering non-dot output files {non_dot_files}","messagePattern":"Graphviz dot executable not available for rendering non-dot output files (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/runners/render.py","lineNumber":428,"sourceCode":"    if render_options.log_proto:\n      _LOGGER.info(pipeline_proto)\n    renderer = PipelineRenderer(pipeline_proto, render_options)\n    try:\n      subprocess.run(['dot', '-V'], capture_output=True, check=True)\n    except FileNotFoundError as exn:\n      # If dot is not available, we can at least output the raw .dot files.\n      dot_files = [\n          output for output in render_options.render_output\n          if output.endswith('.dot')\n      ]\n      for output in dot_files:\n        with open(output, 'w') as fout:\n          fout.write(renderer.to_dot())\n          _LOGGER.info(\"Wrote pipeline as %s\", output)\n\n      non_dot_files = set(render_options.render_output) - set(dot_files)\n      if non_dot_files:\n        raise RuntimeError(\n            \"Graphviz dot executable not available \"\n            f\"for rendering non-dot output files {non_dot_files}\") from exn\n      elif render_options.render_port >= 0:\n        raise RuntimeError(\n            \"Graphviz dot executable not available for serving\") from exn\n\n      return RenderPipelineResult(None)\n\n    renderer.page()\n\n    if render_options.render_port >= 0:\n      # TODO: If this gets more complex, we could consider taking on a\n      # framework like Flask as a dependency.\n      class RequestHandler(http.server.BaseHTTPRequestHandler):\n        def do_GET(self):\n          parts = urllib.parse.urlparse(self.path)\n          args = urllib.parse.parse_qs(parts.query)\n          renderer.update(**args)","sourceCodeStart":410,"sourceCodeEnd":446,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/runners/render.py#L410-L446","documentation":"When the Graphviz 'dot' executable is unavailable, the renderer can only write raw .dot text files. If any requested --render_output files are non-dot formats (png, svg, etc.), it raises RuntimeError chained from the original 'dot -V' failure, listing the unrenderable files.","triggerScenarios":"Requesting --render_output=graph.png (or .svg/.jpg) on a machine where graphviz is not installed, so 'dot -V' fails and non-dot outputs cannot be produced.","commonSituations":"CI containers or slim Docker images without graphviz; forgetting to install graphviz after switching output format from .dot to .png; macOS/Windows dev machines missing the dot binary.","solutions":["Install Graphviz so the dot executable is available (apt-get install graphviz / brew install graphviz / choco install graphviz)","Verify with 'dot -V' that dot is on PATH","Render to a .dot file instead, and convert it elsewhere where graphviz exists"],"exampleFix":"# before\n--render_output=graph.png   # on host without graphviz\n# after\napt-get install -y graphviz && dot -V  # then rerun with --render_output=graph.png","handlingStrategy":"fallback","validationCode":"import shutil\nnon_dot = [o for o in render_outputs if not o.endswith('.dot')]\nif non_dot and shutil.which('dot') is None:\n    raise SystemExit('Install graphviz (apt-get install graphviz) for non-dot render outputs')","typeGuard":"def graphviz_available() -> bool:\n    import shutil\n    return shutil.which('dot') is not None","tryCatchPattern":"try:\n    result = pipeline.run()\nexcept RuntimeError as e:\n    if 'dot executable not available' in str(e):\n        outputs = [o for o in render_outputs if o.endswith('.dot')]  # fallback: dot text only\n        rerun_with_outputs(outputs)\n    else:\n        raise","preventionTips":["Install graphviz in every image that renders pipeline graphs","Assert 'dot -V' succeeds in CI before render jobs","Prefer .dot outputs in minimal environments, converting elsewhere"],"tags":["python","apache-beam","graphviz","render","missing-binary"],"backgroundTag":"command-not-found","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}