# How to Troubleshoot Rendering Issues with lint-render.py

> Troubleshoot rendering issues with lint-render.py, a headless Chromium linter for HTML examples. Detect clipping, overflow, and missing assets by rendering pages and comparing screenshots.

- Repository: [Cathryn Lavery/diagram-design](https://github.com/cathrynlavery/diagram-design)
- Tags: how-to-guide
- Published: 2026-09-12

---

**[`lint-render.py`](https://github.com/cathrynlavery/diagram-design/blob/main/lint-render.py) is a headless-Chromium based linter that validates HTML examples in the cathrynlavery/diagram-design repository by rendering pages and comparing authored versus released screenshots to detect clipping, overflow, and missing assets.**

When diagrams fail visual validation in the cathrynlavery/diagram-design repository, understanding how to troubleshoot rendering issues with lint-render.py requires tracing its three-stage execution pipeline. The script located at [`scripts/lint-render.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/lint-render.py) uses Playwright to isolate network dependencies, measure SVG bounding boxes, and perform pixel-perfect diffs to ensure design integrity. Mastering its error signatures and environment requirements allows you to quickly resolve false positives and actual rendering defects.

## Understanding the lint-render.py Architecture

The linter operates through a strict sequence of browser isolation, DOM measurement, and visual comparison. Each stage contains specific failure modes that produce distinct error signatures.

### Browser Launch and Network Isolation

The script initializes by creating a Playwright Chromium context via `launch` at lines 10-19. Immediately, the `block_network` function at lines 22-41 enforces strict network isolation using a `resolver_rule` at lines 30-36 that blocks all external hostnames. This guarantees only local assets from `ASSET_DIR` (defined at lines 86-88) are loaded. If Playwright cannot locate the bundled Chromium binary, the script aborts early with error messages at lines 99-106.

### Page Rendering and Measurement

For each HTML file processed, the execution follows this exact sequence:

- **`page.goto`** at lines 94-95 loads the target asset
- **`SURVEY_JS`** (lines 16-45) inventories every `<svg>` element in the DOM
- **`RELEASE_JS`** (lines 84-110) programmatically removes overflow constraints from the SVG and its clipping ancestors
- **`shoot`** at lines 65-69 captures two screenshots: the authored state and the released state
- **`DIFF_JS`** (lines 26-61) performs pixel-by-pixel comparison to detect ink spilling outside the released bounds

### Reporting and Self-Verification

Findings are classified into categories such as `clipped`, `page-overflow`, `svg-collapsed`, and `unmeasurable` within the `clipping_findings` logic at lines 13-74. The `--self-test` flag triggers the `self_test` routine at lines 99-176 to validate the detection logic, DOM restoration, and network isolation integrity before processing actual assets.

## Diagnosing Common Rendering Failures

Match the symptom to the specific code path generating the error to troubleshoot rendering issues with lint-render.py effectively.

**`render-error` with traceback:** Indicates Playwright crashed or the HTML contains runtime JavaScript errors. Inspect exception handling around `check` at lines 21-23 to isolate the failure.

**`page-overflow` reported:** The document width exceeds the viewport dimensions defined in `VIEWPORT` at lines 89-90. The detection logic resides in `PAGE_OVERFLOW_JS` at lines 15-20. Verify your CSS does not force fixed widths exceeding the default 1600×1000 pixel canvas.

**`clipped` findings:** Content spills outside the SVG boundaries or a clipping ancestor. Review the diff logic in `DIFF_JS` (lines 26-61) and the release stages in `clipping_findings` to identify which ancestor is trapping content.

**`unmeasurable` due to scrolling ancestor:** A parent element has scrollable overflow, preventing accurate bounding box calculation. The early exit logic at lines 23-30 of `clipping_findings` aborts measurement to avoid false positives. Remove scrolling from parent containers or restructure the HTML.

**`missing-asset` errors:** Local images or scripts failed to load. Inspect `on_request_failed` in the `watch` function at lines 56-60 to identify broken relative paths in `skills/diagram-design/assets/`.

**Self-test failures:** Indicates corrupted linting logic or environment misconfiguration. Run `python3 scripts/lint-render.py --self-test` (entry point at lines 99-106) to determine whether the issue lies in the linter itself or the target assets.

## Fixing Environment and Configuration Issues

Many rendering issues originate from environment setup rather than code defects.

### Playwright Installation and Chromium Versions

If the script exits with code `2` indicating environment errors, verify Playwright is installed correctly. The script prints installation hints at lines 81-87. Execute:

```bash
pip install playwright && playwright install chromium

```

For consistent results between local and CI environments, align your Playwright version with the pinned version in [`.github/workflows/ci.yml`](https://github.com/cathrynlavery/diagram-design/blob/main/.github/workflows/ci.yml). Version mismatches between local Chromium and CI Chromium often produce subtle pixel differences in `DIFF_JS` comparisons.

### Font Rendering and Network Isolation

By default, [`lint-render.py`](https://github.com/cathrynlavery/diagram-design/blob/main/lint-render.py) blocks all external hostnames via `RESOLVER_RULE` at lines 6-7 to prevent network dependencies. If diagrams rely on Google Fonts for accurate typography measurement, enable them with the `--fonts` flag (argument parsing at lines 64-78). If you encounter unexpected "network-isolation" failures, verify `RESOLVER_RULE` remains intact and no environment variables override the resolver configuration.

## Practical Debugging Commands

Use these specific invocations to isolate different classes of rendering issues:

```bash

# Render all examples with default 1600×1000 viewport

python3 scripts/lint-render.py --all

# Test a single file quietly to isolate specific failures

python3 scripts/lint-render.py path/to/example.html --quiet

# Enable web fonts for accurate typography measurement

python3 scripts/lint-render.py --fonts --all

# Verify the linter's own detection logic is functioning

python3 scripts/lint-render.py --self-test

```

Exit codes indicate result severity: `0` for no findings, `1` for detected issues requiring fixes, and `2` for usage or environment errors (see `main` return values at lines 95-106).

## Summary

- [`lint-render.py`](https://github.com/cathrynlavery/diagram-design/blob/main/lint-render.py) uses Playwright to render HTML assets and detect visual clipping through pixel comparison in `DIFF_JS` (lines 26-61)
- Network isolation via `resolver_rule` (lines 30-36) and `block_network` (lines 22-41) ensures reproducible local rendering without external dependencies
- Common failures include `render-error` (Playwright crashes), `page-overflow` (viewport mismatches in `VIEWPORT` at lines 89-90), and `clipped` (content spillage)
- The `--self-test` flag validates the linter's internal logic through `self_test` at lines 99-176
- Environment issues often resolve by matching the CI Playwright version in [`.github/workflows/ci.yml`](https://github.com/cathrynlavery/diagram-design/blob/main/.github/workflows/ci.yml) and ensuring Chromium is installed via `playwright install chromium`

## Frequently Asked Questions

### Why does lint-render.py fail with a Playwright installation error even after I installed the Python package?

The script requires both the Python package and the browser binaries. As indicated at lines 81-87 of [`scripts/lint-render.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/lint-render.py), you must run `playwright install chromium` after `pip install playwright` to download the bundled Chromium binary that the `launch` function at lines 10-19 expects to locate in the system path.

### How do I fix false positives for page-overflow errors?

Check the `VIEWPORT` constant at lines 89-90, which defaults to 1600×1000 pixels. If your diagram's natural width exceeds these dimensions, either refactor the CSS or modify the viewport configuration. The detection occurs in `PAGE_OVERFLOW_JS` at lines 15-20, which flags any content exceeding these bounds.

### What causes `unmeasurable` findings in the lint-render.py output?

This occurs when an ancestor element has `overflow: scroll` or `overflow: auto`, preventing the script from calculating accurate bounding boxes. The early exit logic at lines 23-30 of `clipping_findings` aborts measurement to avoid false positives. Remove scrolling properties from parent containers or adjust the HTML structure to eliminate scrolling ancestors.

### Can I allow external resources like Google Fonts during rendering?

Yes. By default, `RESOLVER_RULE` at lines 6-7 blocks all hostnames, but the `--fonts` flag (parsed at lines 64-78) explicitly enables Google Font hosts while maintaining isolation for other domains. Use this flag when text metrics affect your visual diff results, but ensure you do not introduce network-dependent assets that would fail in CI environments.