nexu-io/open-design · error · OverflowError
cursor at {self.y} exceeds footer rail {self.cap}; reduce bl
Error message
cursor at {self.y} exceeds footer rail {self.cap}; reduce block height or split slide What it means
Raised by the Cursor.take() helper documented in skills/pptx-html-fidelity-audit/SKILL.md when advancing the content cursor would push self.y past self.cap (CONTENT_MAX_Y, the footer rail). It is an intentional OverflowError that turns a silent visual overflow (content crossing the footer) into a loud build error during pptx re-export.
Source
Thrown at skills/pptx-html-fidelity-audit/SKILL.md:136
FOOTER_TOP = Inches(6.85) # footer row pinned here, edge-to-edge
```
> **Customizing the rails.** The defaults above suit a 16:9 canvas with a slim footer. If your design system uses a wider footer or a 4:3 canvas, override these constants in your export script and pass the same values to `verify_layout.py` via `--content-max-y` / `--canvas-h` / `--canvas-w`. See `references/layout-discipline.md` §1 for the full constant table.
**Use a cursor for content blocks instead of pinning each block at an absolute y:**
```python
class Cursor:
"""Advances down the slide; refuses to cross the footer rail."""
def __init__(self, y_start, cap=CONTENT_MAX_Y):
self.y = y_start
self.cap = cap
def take(self, h, gap=Inches(0.12)): # ~1 line of whitespace at 14pt; tighten/loosen per design system
top = self.y
self.y = top + h + gap
if self.y > self.cap:
raise OverflowError(
f"cursor at {self.y} exceeds footer rail {self.cap}; "
f"reduce block height or split slide"
)
return top
```
For each slide, instantiate `Cursor(MARGIN_TOP)` and `take(height)` each block in reading order. The slide refuses to render if any block would cross the rail, so overflows become loud build errors instead of silent visual bugs.
**Hero (vertically-centered) slides use a budget instead of a cursor:**
```python
def hero_layout(blocks):
"""blocks = list of (height, gap_after) tuples in reading order."""
total = sum(h + g for h, g in blocks)
y_start = (CANVAS_H - total) / 2
return Cursor(y_start)
```
View on GitHub (pinned to 5be4028344)
Solutions
- Reduce the offending block's height (tighten image height, trim text, shrink padding).
- Split the slide into two slides so each fits within the rail.
- Raise CONTENT_MAX_Y only if the design system genuinely allows a smaller footer (update FOOTER_TOP accordingly and pass --content-max-y to verify_layout.py).
- Switch the slide to hero_layout (centered budget) if it is a vertically-centered hero, not a top-pinned flow.
Example fix
# before cursor = Cursor(MARGIN_TOP) cursor.take(Inches(6.5)) # single block too tall, raises OverflowError # after cursor.take(Inches(3.0)) cursor.take(Inches(2.8)) # split into two blocks that fit
Defensive patterns
Strategy: try-catch
Validate before calling
if cursor.y + h + gap > cursor.cap:
raise SystemExit(f"block of height {h} would overflow footer rail; split or shrink") Try / catch
try:
top = cursor.take(block_height)
except OverflowError as e:
# split the slide or shrink the block, then retry
split_or_shrink(block, e)
raise Prevention
- Compute per-block heights from text metrics + minimal padding, not generous wrappers.
- Keep CONTENT_MAX_Y and FOOTER_TOP defined once per deck and passed to verify_layout.py.
- Use hero_layout for centered slides instead of a top-pinned Cursor.
- Run verify_layout.py after every re-export so overflows are caught early.
When it happens
Trigger: Calling cursor.take(h) for a block whose height plus gap pushes the running y beyond CONTENT_MAX_Y; too many blocks stacked in reading order; a single oversized block (e.g. a tall image or long bullet list).
Common situations: Re-exporting a deck where a slide has more content than the content area allows; design system changed footer height so CONTENT_MAX_Y shrank; image heights computed too generously.
Related errors
- Cursor exceeded rail at '{label}': y={self.y} cap={self.cap}
- no slides to export
- --page/--no-deck is not valid with --format pptx
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/65052b9ce971e9aa.
Report an issue: GitHub.