Skip to content

πŸ› Bug Report β€” Runtime APIs: Images binding crashes with "Cannot read properties of undefined (reading 'font')" when input() is given an ArrayBuffer #7126

Description

@nobuhiko

Summary

Since the rollout of the Images text rasterization feature (IMAGES-2451, #81681765 merged 2026-08-12), passing an ArrayBuffer to env.IMAGES.input() crashes every .output() call with:

TypeError: Cannot read properties of undefined (reading 'font')
    at serializeTextSource (cloudflare-internal:images-api:14:30)
    at cloudflare-internal:images-api:88:47
    at withSpan (cloudflare-internal:tracing-helpers:37:20)
    at ImageTransformerImpl.output (cloudflare-internal:images-api:82:22)

This worked fine before the rollout (our Worker ran unchanged in production since 2026-08-14 and broke around 2026-08-25 with no deploy on our side). Changing compatibility_date does not avoid it.

Repro

export default {
  async fetch(request, env) {
    const body = await request.arrayBuffer();
    const result = await env.IMAGES.input(body)          // ArrayBuffer input
      .transform({ width: 1200 })                        // any transform, or none
      .output({ format: 'image/jpeg' });                 // -> TypeError (reading 'font')
    return result.response();
  },
};

Any transform combination fails identically (plain resize, segment, etc.), and the error is thrown in ~60ms, before reaching the backend.

Root cause

isTextSource() classifies the input source by elimination:

function isTextSource(source: ImageSource): source is TextRasterize {
  return !(source instanceof ReadableStream);
}

An ArrayBuffer is not a ReadableStream, so it is misclassified as a text source, and serializeTextSource() dereferences source.options.font β†’ undefined.font β†’ TypeError.

Expected behavior

Either:

  1. Keep accepting raw bytes (ArrayBuffer/TypedArray) as before β€” the Images binding docs say .input() "Accepts image bytes up to 20 MB from any source", and the pre-2451 implementation passed the source straight through to the form serializer, so ArrayBuffer worked in practice; or
  2. If only ReadableStream is supported (as the TS types say), throw a clear ImagesError (e.g. "input must be a ReadableStream") instead of an internal TypeError about 'font' that gives no hint the input type is the problem.

A positive check for the text-source shape (e.g. typeof source.content === 'string') instead of elimination against ReadableStream would fix both.

Workaround

Wrap the buffer: env.IMAGES.input(new Blob([body]).stream()).

Impact

Silent production breakage for any deployed Worker that passed bytes rather than a stream β€” no deploy on the user's side, not mitigated by compatibility_date, and the error message points at fonts rather than the input type, which makes it expensive to diagnose.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions