#Worker hangs when img requested with `decoding="async"`

1 messages · Page 1 of 1 (latest)

spark mesa
#

I have an API endpoint set up to serve photos from an R2 bucket. The endpoint looks like this:

import { env } from "cloudflare:workers";
import { route } from "rwsdk/router";
import type { RequestInfo } from "rwsdk/worker";
import { STATUS } from "@/constants";

type PhotoByFileNameRequest = RequestInfo<{
  fileName: string;
}>;

const photoByFileName = route("/photo/:fileName", async request => {
  const {
    params: { fileName },
  } = request as PhotoByFileNameRequest;
  try {
    const object = await env.PHOTOS.get(fileName);

    if (!object) {
      return new Response("Photo not found", {
        status: STATUS.NotFound404.code,
      });
    }

    const headers = new Headers();
    object.writeHttpMetadata(headers);
    headers.set("Content-Type", object.httpMetadata?.contentType || "image/*");
    headers.set("Cache-Control", "public, max-age=31536000");

    return new Response(object.body, {
      headers,
    });
  } catch (error) {
    return new Response(JSON.stringify(error), {
      status: STATUS.InternalServerError500.code,
    });
  }
});

export const apiPhotoRoutes = photoByFileName;

Error is:

[vite] Internal server error: The Workers runtime canceled this request because it detected that your Worker's code had hung and would never generate a response. Refer to: https://developers.cloudflare.com/workers/observability/errors/
Warning: A promise was resolved or rejected from a different request context than the one it was created in. However, the creating request has already been completed or canceled. Continuations for that request are unlikely to run safely and have been canceled. If this behavior breaks your worker, consider setting the `no_handle_cross_request_promise_resolution` compatibility flag for your worker.
    at Object.resolve (<anonymous>)

The client shows 500s for each failed req, but my route's catch isn't getting any errors. Also, all the images resolve as individual URLs

#

Consistently, I'll get this error for anywhere between 2-5 of the requests.

I found this issue with the cloudflare vite plugin that I was hoping to be the cause. But I'm on 1.11.0 already, which contains the purported fix

GitHub

What versions & operating system are you using? 4.19.1 [wrangler], 4.7.7 [hono], 7.5.2 [react-router] (but have tried many versions of each) Please provide a link to a minimal reproduction No r...

GitHub

Fixes #9518.
Fix issue that resulted in A hanging Promise was canceled errors when developing large applications.
We now handle requests for modules in a Durable Object so that they can be shared a...

#

I'm fetching the photos like so:

export const HomeLayout = async ({ children, requestInfo }: LayoutProps) => {
  const photos = await db.photo.findMany({
    orderBy: {
      createdAt: "desc",
    },
  });

  // ...

  return (
    ...
    {photos.map(photo => (
      <PhotoItem key={photo.id} photo={photo} />
    ))}
    ...
  )
};
export const PhotoItem = ({
  photo,
  showUploader = false,
  showDate = false,
}: Props) => {
  const src = link("/photo/:fileName", {
    fileName: photo.fileName,
  });

  const created = new Date(photo.createdAt).toLocaleDateString();
  const alt = `Uploaded${
    photo.uploaderName ? ` by ${photo.uploaderName}` : ""
  } on ${created}`;

  return (
    <div>
      <Image src={src} alt={alt} />
      {showUploader && photo.uploaderName && (
        <p>Uploaded by: {photo.uploaderName}</p>
      )}
      {showDate && <p>Uploaded: {created}</p>}
    </div>
  );
};
type Props = {
  src: string;
  alt: string;
  width?: number;
  height?: number;
  loading?: "lazy" | "eager";
  className?: string;
};

export const Image = ({
  src,
  alt,
  width,
  height,
  loading = "lazy",
  className,
}: Props) => {
  return (
    <img
      className={className}
      src={src}
      alt={alt}
      width={width}
      height={height}
      loading={loading}
      decoding="async"
    />
  );
};
#

Worker hangs when img requested with decoding="async"

#

When I remove decoding="async", no more worker issues 🎉

I'm not sure this is actually due to anything rwsdk is doing. In fact the error sounds like the right description for the issue -- image request resolves separately from the decoding pass. So maybe it's just something that shouldn't be used with SSR? Though I'd expect this behavior to only matter on the client since it is render bound:

The decoding property provides a hint to the browser as to whether it should perform image decoding along with other tasks in a single step ("sync"), or allow other content to be rendered before this completes ("async"). In reality, the differences between the two values are often difficult to perceive and, where there are differences, there is often a better way.

In fact, firefox uses this as the default behavior

https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decoding

solar badger
#

Thanks for the detailed writeup and investigating! Interesting, right I wonder what behaviour might be triggering in the SSR case when decoding=async is provided. Because to your point nothing should be looking at that attr server side

polar vigil
#

Very strange.