wevm / frog

Framework for Farcaster Frames 🐸
https://frog.fm
Other
423 stars 97 forks source link

Failed external API calls kill the frame, even if that frame doesn't use the awaited data #267

Closed titusdecali closed 6 months ago

titusdecali commented 6 months ago

Describe the bug

In my use case, I am fetching balances from an external server and then binding in the resulting data to the frame before rendering the image.

However, if the API returns aa 400-based error code, the frame will die with the following error in console:

  [cause]: TypeError: Invalid URL
      at new URL (node:internal/url:783:36)
      at new _Request (node:internal/deps/undici/undici:5055:25)
      at fetch2 (node:internal/deps/undici/undici:9195:25)
      at Object.fetch (node:internal/deps/undici/undici:11370:18)
      at fetch (node:internal/process/pre_execution:314:27)
      at global.fetch (file:///Users/lotus/Documents/quidli-farcaster_demo/node_modules/@hono/node-server/dist/index.mjs:258:10)
      at getImageSize (file:///Users/lotus/Documents/quidli-farcaster_demo/node_modules/frog/_lib/dev/utils/getImageSize.js:2:28)
      at file:///Users/lotus/Documents/quidli-farcaster_demo/node_modules/frog/_lib/dev/api.js:58:13
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
      at async dispatch (file:///Users/lotus/Documents/quidli-farcaster_demo/node_modules/hono/dist/compose.js:29:17) {
    code: 'ERR_INVALID_URL',
    input: 'undefined'
  }

This is obviously an issue, because the frame should be able to display an error in the case an error occurs. It seems to me that the only way around this is to have our API return a 200 code, regardless of the result, then pass an error code to display to the user, which is a VERY BAD dev experience.

Even if the API call is unrelated to the template being generated, it will kill the frame the moment the 400 code arrives.

I've tested this within a Next.js app, and using straight TS with Vite, and both result in the same issue.

Link to Minimal Reproducible Example

No response

Steps To Reproduce

Add an async await within any app.frame, before the c.res and in the case the endpoint returns a 400 series code the frame will display nothing and the console error mentioned above is shown.

EX: SHOT 17 20 09@2x

Frog Version

0.8.5

TypeScript Version

5.3.3

Check existing issues

Anything else?

No response

dalechyn commented 6 months ago

a bit confused here, are you referring to fetchBalance method throwing in a frame that kills it?

can you wrap it with try catch block?

titusdecali commented 6 months ago

Yes, the fetchBalance method has a try / catch inside of it. When it catches an error, the frame gets killed.

fetch

titusdecali commented 6 months ago

FYI: To skirt this issue we've restructured our API response to always return a 200 code, and use the following parent object to handle errors. This is possible for internal APIs, but for third-party APIs that return typical 400-series codes, the issue above will cause frames to die in the water.

If you have a better way around this issue without the 400 -> 200 change, I'd be happy to implement it.

SHOT 09 21 46@2x

dalechyn commented 6 months ago

can you please add a minimal reproducible example?