Red Eye Tickets

Production incident

An unexpected event title exposed a hidden assumption in our PDF pipeline

A producer used an emoji in an event title. The product accepted the title, but the ticket renderer had a narrower character contract. The input triggered the incident; the system mismatch caused it.

Incident class: document generationCommitted remediationBlameless review
01

What happened

A producer created an event whose title included an emoji. The web workflow and stored event record allowed the title, but generating a customer ticket PDF crossed into a renderer and font path built around Windows-1252-era assumptions. Ticket generation could fail when that title reached the document boundary.

The behavior was legitimate and creative, not malicious. A title is naturally expressive content; there was no reason a producer should have known that a downstream PDF library had different encoding limits.

02

Impact and evidence limits

The failure threatened the most important artifact after purchase: a usable ticket. It also created support risk because the event could look healthy in the product while failing only when a document was rendered.

Historical incident counts, exact duration, and the number of affected buyers are not preserved in the portfolio evidence, so this review does not invent them. The durable evidence is the renderer hardening and the regression case that saves an event titled Cafe 🍩 and verifies a readable PDF is still produced.

03

How I narrowed the failure

The original alert transcript and timestamps are not preserved, so this is the bounded diagnostic path supported by the failure and the committed regression—not a reconstructed minute-by-minute timeline.

  1. Reproduce the boundary: generate a ticket from a saved event title containing an emoji.
  2. Separate accepted input from failed output: confirm the web and storage path can hold the title, then isolate the failure to PDF generation.
  3. Test the encoding hypothesis: compare general UTF-8 text with what the selected Prawn font and legacy character path can represent.
  4. Turn the repro into proof: keep Cafe 🍩 as a renderer regression and require a readable PDF result.

That sequence changed the question from “which title broke?” to “where do our character contracts diverge?”—the distinction that led to layered remediation instead of a one-off data edit.

04

Root cause

  1. Product contract: event titles behaved like general text.
  2. Storage contract: the title could be persisted and reused across product surfaces.
  3. Document contract: the renderer depended on narrower font and encoding support.
  4. Test gap: the boundary lacked a representative non-Windows-1252 title case.

The root cause was not “a user entered an emoji.” It was that character support was implicit and inconsistent across the end-to-end workflow.

05

Resolution

Prefer Unicode fonts

The PDF layer searches for Noto Sans or DejaVu Sans and keeps its text in UTF-8 when compatible fonts exist.

Sanitize at the boundary

A single PDF text sanitizer replaces invalid byte sequences instead of letting raw display text reach Prawn unchecked.

Fail soft

If the library raises an incompatible-string error, rendering retries through a printable ASCII fallback so ticket delivery can continue.

Make the contract visible

Event-title validation and the producer readiness report surface legacy-character-set risk before the document path is exercised.

Keep the regression

The ticket-renderer spec covers a saved title with an emoji and asserts that a readable PDF is produced. It does not claim the emoji glyph itself is preserved.

Preserve ownership

User behavior is treated as a product input to design for, while remediation stays with the system and its maintainers.

06

What changed in how I build

  • Define text and file-format contracts across the whole workflow, not field by field.
  • Test boundaries with emoji, accents, smart punctuation, malformed bytes, and long content.
  • Make customer-critical artifact generation degrade to a readable result when fidelity is impossible.
  • Write incident language that separates the trigger from the root cause and keeps responsibility with the product.