fix(compose): correct the Cloudflare Images binding contract (F6)#114
Merged
Conversation
Every cf* compose op (cfTransform/cfOverlay/cfBlur/cfSmartCrop/ cfBackgroundFill) threw "cf-images transform failed: HTTP undefined undefined" on the live Worker, despite hasImages:true. The stub CFImagesBinding interface — written before the real binding shipped — modeled .output() as Promise<Response>, but the live Images binding resolves to an ImageTransformationResult whose .response() yields the Response (it also exposes .image()/.contentType()). transform() read .ok/.status/.statusText/ .arrayBuffer() straight off the result object — all undefined — so it threw on every call. The unit test mocked the same wrong shape, so CI stayed green while production was 100% broken. Model the result correctly (CFImagesTransformResult.response()) and route through it. A new toResponse() guard surfaces a clean, actionable error when the runtime hands back an unexpected shape (e.g. Images Transformations not enabled on the account) instead of the "HTTP undefined undefined" — the binding result is no longer assumed to be a Response. This is a code fix, not a provisioning gap: execution reached the transform call past the `if (!ctx.images)` guard, so the binding is injected. Whether Images Transformations is actually enabled is confirmed at the gated deploy + live verify; if a cf* op still fails there, the existing missing-binding guidance + in-isolate fallbacks (compose.ts) degrade cleanly. Tests: fixed both mock bindings (core + mcp compose) to the real .response() contract — so they validate reality, not the stub; added a malformed-result case at the core layer and end-to-end through the tool, asserting a clean error and NOT "HTTP undefined undefined". Suite 675 -> 677. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Jim Vinson <jim@vinson.org>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
F6 —
limner_composecf-images opsEvery
cf*compose op (cfTransform/cfOverlay/cfBlur/cfSmartCrop/cfBackgroundFill) threwcf-images transform failed: HTTP undefined undefinedon the live Worker, despitehasImages:true.Root cause — a code bug, not provisioning
The stub
CFImagesBindinginterface (written in Phase 3 before the real binding shipped) modeled.output()asPromise<Response>. But the live Cloudflare Images binding resolves to anImageTransformationResultwhose.response()yields theResponse(it also exposes.image()/.contentType()).transform()read.ok/.status/.statusText/.arrayBuffer()straight off the result object — allundefined— so!response.okwas always true and it threw on every call. The unit test mocked the same wrong shape, so CI stayed green while production was 100% broken (CF docs).Fix
CFImagesTransformResult.response()) and route through it.toResponse()guard: when the runtime hands back an unexpected shape (e.g. Images Transformations not enabled and the binding returns a stub), surface a clean, actionable error instead ofHTTP undefined undefined.Provisioning
This is a code fix. Execution reached the transform call past the
if (!ctx.images)guard, so the binding is injected — strongly implying Images Transformations is already enabled on the account. That's confirmed at the gated deploy + live verify; if acf*op still fails there, the existing missing-binding guidance + in-isolate fallbacks (compose.ts) degrade cleanly. I'll surface the provision-vs-degrade decision at the checkpoint only if live verification still fails.Tests
cf-images-transform.test.ts+ mcpcompose.test.ts) to the real.response()contract — so they validate reality, not the stub (a regression to the old "treat result as Response" shape now fails).HTTP undefined undefined.Suite 675 → 677. Typecheck + lint clean.
🤖 Generated with Claude Code