satori
satori copied to clipboard
Image in SVG doesn't work when exported to PNG
Bug report
Description / Observed Behavior
Image in SVG doesn't seem to work when exported to PNG – it throws this error:
Cannot read properties of undefined (reading '0')
Expected Behavior
Render the PNG the same way as it does the SVG.
Reproduction
Repro: https://d.to/k3beO8I
(click on the "PNG" tab)
Additional Context
Related PR: https://github.com/vercel/satori/pull/472
cc: @Jackie1210
Having same issue here.
@steven-tey any solution?
@Jackie1210
https://og-playground.vercel.app/?share=xVvbbtvIlv2VwIPBeegMWjc3kpzuAzim49BjUlEsWaHRLzalUKIkO4ikSGSj_33WWruKpGwnPZcG5kHYvBSrdu37pfTHUfowmR69Ofp1Mv_2-2LF-tNsZz-9scfvH7xYjadZ7PNmxf_aLda__6Pl_ZwN59sZo-eTebrL8vbAk8_L6d7_5TXwfzrNN3MH-7xLn1Yblf3_u3tcp7dh5vpas1X0_vN9Kt_lW_Xm_nn4vQBD--5_uHru9t0kX192N5PTh-WD1_x_t8-f_5crYqvrubl9M2LbqfxaOz28kurpad__vn7_b948et8dZtNbVu__X6Ebf1-5HZe336dfsbN5HZz-0bDf15_y37ar5b_TGe3X9fTzW_bzef_ePXPu9v19Jfeyw_v485N8bZzO77uDlavex-uwl0YnGTR8Oz4Mh-14-JkHwXJtn8VZtPz9vruPnodrmatyfuTXy6L191JN91Oymh71724vyzDXRScfEu7N_fh_O0i-fRxdjk-nt2NR6_DxX42HV8XYXA2D8-Xiw9XF1HyablMl6_2Yd77z_D05NXkfNm6Ox_9NPh00UpWr2fpapBF5eDVZffjl8n5fvkhe8jCYH8veHqSfXj_djY5z7Kb1XJ9F7TmYXmxiPLBPirC7Ab3w-HZLpr39nG5WEflchYNB9t-MDi-DM5al3nW6l_tdpfByTo6bfUu83CNse2kaG3jq155edXD_pNNdNXD2OUa9-3LPNpc5gs-w_UZrt_ll3kKmK3xrLwcnm3j-a64HIbb-Hy3jeatbdSJDM41J74bYfxkbXN9xPchYLiNbN02xnSTIb7JT4Cnh8QRuJ66OYKzHfAoo_luH532jqMSuPM9xgEX4Xd32iswFrhznZvS1hnZOoXeuf2kws_tuXswrnNWYEw7PsWeDDp62d763CPG9cfA8wp7tHkxR0Qc9hhre8O7-BT32htoUybYk4fV3vj-OCkb33AOzqd5bI0Y_BRv_HcVL27GUf5uhnWP4yHo4aHhjPccM8nBa-ACXDkXcAfc4x1lwPgkXA_eV_d9G4PxFzPsp4zKaO2hrcM1-LvOgRfx7OAnuXDz4NvU1iK9-PNrvk9Mnuy7lr7jPnnN7ztn4OGiBA88NF64OSB3Hay9j64q6GUbdOS6okkrasIKZ_I8WZO20PsK1rRLpQd3jkbx-dmeY_rBaB0Nk200zCCTjh_DM47taSxlaEwZ429AuZL-OBnl_rhXygyvuWf-jGb1NWlw7GigvcWF7RGw3iN_K78OaSk9hS5CJ0V36H8BnIeDdQXd_qCbRuMryTntQNnYD2W3RXntDyPIoofN9-RJAlpAl3K-O6MelRV-VzvIEud-B_2E3K_OYG8gNcXOw3rc6Q64XmMc5h2Dj_NeLyZO0Jt-kHi89tAX4HS27X8C_VfUDdDKeIvvMR73sAGcCzYGc-n5Avzj_DHGxrP-aW9HHnro5IFr6_sJvuuf01ZCJjiXX1u6DXpp7TPo3wnkYedhQy651gXXMrmWHNBGyh4eS0bAa9rcSh7EO-z1fKex0o9CMkC8qXc92A3iI1jLaAR7dfANZQc092tTxjFGskLamE12a5scCj-MeU8IG-TstskyxtIuD9NCdlmwogf2CJ5pjgvaoLIfiBcGKz0bQIaJI76XrJpdcHYTdI45B3B9R950-9BBD_0ckhHgFAfgZUlfVuFA-eJeAbmW-R3a9TvySvJHX2X-a8K9jUUv96NuLo1WDbtNXeH-YUMot5y7Z_5AsOK16Kr5vL5n-M28PfN67mGRDEfbeDjoXQYeVva8R3oaXx7ZSPJBOCAmka4KVjaA9jk-F13djzwX3fGDzYbMRZQdB728mw8AnwrosceDtAbPTd9heyvo9R73p63iVjjB30FPSbc-5Zj-byg70uN74kR553v43i5tBr5FfKHnbflEZ1sM1rbFZJB7zXrGQ0G_Z9xjH5Q_xQSjAjENY4J2lCPm8faNOJHO0EfiZ3ab8tO023gvmt54GXSydBA3tG-Dt_bceMl4xXw-5Yx7le45vtF-Fb2d4hPqThDVOkO7Cbp7n-L0wf2kf45v0gknM8_qH2WGuo6Yx63dac7l5UA_P562xv_oZ5oy6n_Qd-jAMANtPax0zcdyoA9-TR3kfBwfLKBHHlZ4yqdVeyaupOsq4rvHeuLsDuT6OinM_58cQxY8PPD_zl5aTOm-f8Qj88nUI9n0DHLGeJjxSB270GfKNmg9-Ursp8IffHs3ls_vCGfFXrRJpkPX5EOLuh0F8NWQOYOVz5I_jlYabzGn5MDwTWBrzJYqfgRtBy6WsH2494pbzVdqTfpUxn-I73_kf6kr0HXpPvbsYa0jiAFg-6VrKeMrD72uYS3Ko2hiMuh5ID3Ec9nOkPzpch7KftNHaQ36bNnJgYtXnE-ifVBcyzjHv4f-gG4-tjcbR5_6kTqBdRRnMvZgjMb1SV9C47X3b7AxLm_w42BzQPcgxD48rHhMG-B0n_uNzK7Crnj_bfZY8kX5l6-gf4BdMv5wTvMttNe0AZ2IORjpm0fN2F308H4b8Q5jiAL88rDat4slEL-7vMrrLfiuWKDYOZluyCppeZ8wBmV-QRrYM_kVzsec4VpzKr5hLoTnpE2UMzfxsJGjkDbE1Y8XXsg75rRzsKse1rEUaWG0oR2lflCO5Z-VK0k-Td41r9lg0l3PriHXJ7DVC9hw2vjo-HG8qFyP8iJcmEs6XeEauOY7xHHmsyXfgnUuxzHywyno52Gls_h-JnzgxyyPxT4gr8AdPsTiJs4B-mN_c4eL9Njpl-YAH_AN5ZI-CvuyvIi2y_Ii5YygPcamO8o55uhGAXJrpz-IhSy3Rk4B2sif0haB9_R5nI-6DxrNFOtLR5t5kHQa8WBFZ_BPfFF8ZXGg4h7afrONTraatMK-uZeaB6bXI-4LuFd-FzQj3fUe84FW-QLjPGzQN3j3EGGcbADXV83A6Ir1MafJw18_93RnfYHxK2KSPONY2lbJl2Ia8k_yq3t9Z7Dx_r14Sv2mL5DMYH8eVvSgDcfcrC8wPqA-Y23ihTldvGixmmAtt_Jv1Zrw7aT3QvQ-mB9zYxxk64K1EtIS-9Za7nvoHmkQpKwpyPY2vme8tI7GGWMRXC9g5xjHNesl4McK74ErZGjHPM1BPwfWpsxlyvups5bLVTpC-VZ-YjqHfTOGtVysuIb9MJkeIfaSTLcRezVlhDZjP8EP8Q14l7Uh-yVkoRcPK9knzbC3Jd6z5gR8mLPKlin2ow118qt4kH7Z4i9fH4INQd5a23nQ2ew07HFueTztB-YljYgHamZcZ1cQl1vQOimZfytvpm9jDAddw9wa19K4RPWAM-ieh9V6intVF6P9Zc5q-QntuK-1sW6lGEjyqn0wBqBu0EZQrujDwAfsB3mDs4mjVh0TU7Y4lv7G58zkfdY5GGM1gXFckp6cE_hqDcq93qkO4WIO5sC-VkZ7D33lnKoZ1vEfacp3ioGIV9alPwEPkKtW9RT5Z8qLaKocg3JAP6q8gHmZ-VPW1WhnvO9S_vY9X1PN4eo7DVi9V25d1awOa1f197QhlBkPG3i7-BZ8zDP5R4MVjxVrOt7V-b747fiuPTXzfa554XCLZ1F5ctwfjjpRnrbjYdKJyxTxCfU22vWHi3ach90Y72PqXz5oxMGWh0N-jG_y4aqDQFabdsdw6Vs-y1qa6qyYu-GzlXe42qzqR76e4OSANktxldXpnhknm-X8CHgEPfCwkhXmTMTX5TaQvwD6T70RbOipxcBuHOcZKHY3WI3juvCvltc4HriaBv1CVTt1tRBX3-gwF0CsbHauEe8arcyuKO-GbKf0hR7W46ATTm9pA62ep3VhU1g3pT3WusrF_LrylZCxuoZhNPPxPmiHvkOQQd48PKiD1-MqHeW-6NOlo9-JARirxwFsE30jfQX6AJJp1toQr7NXQNtxQt_E92X-mH-Id99S8_ftW4D9SoO-hDsXejd6dvV7Xi_Rg8lT8qofROMeuyDoNcRQ6Yhx_RRA-AJm2M1asQz8OXyj-EG-gh-Qgfoc8sB4oKQuU4L7z3-9M0b2uikpF93fQvN0UK8TN8_2iCv555xzX0srI4Nn4X4CTYb32FP9AvwN6x5PKmfaB7mvldcT3gBT8hl0QLutNN8rlwKMRf2JX8YbRivpQVxYu0HeSH3OFcth3qmOgt9nWK45vUnXx9hXKIYljUayHpIO16SPqznN2wd5gbOiMVcv4YyRz_m-jVpFStCz-lzGRvKHuE58zz2T6xGQ79HOgYhvidNwW_YdsgEczk8q-vgFier3mr9Ddpx4i-fkJJObb8m3sPfSRaJO-aCHYPs1dfcZ8b6HnMSxibARfunvSJtmAc7_aBfwDPuE_IsP636L3jLmIJjA8UYa8kO6lj00dy389uMzc1vC0fsU2Pgs1Ubkt8hr0lT0MpkRLyGvSGu-E71DMaA1uvScx8HMGehTlH-qDNtl-sijuoVplPQ4dPdMf0972Par-f0in298_Sn07ldP3dPfbsp6_HVuCf9wLQTdUZFgt6l9QORH6I-4HS-m5ay44zZjA-k_ypq8E579fw64KPpHfIy8BrfMpaC3EOmSj6jjZzcoq-J3qVweow_7ccO_dGH8Pzmy9357nU4R2ZcXi8Q86E_OkC_tHUMmsP_gVaMjRG_Us7VCyCPYWHqWqXkDPy_yKFXjJmAm2q-pnf1tdVVpGeQUeUe5B30hnZCPuDdj_B-ddn5u3iBWLTJC_FBegX9pP3iPpBrS2-hW5JL2gPEJ8wzmtess1kvlLpE-4M9Z5RV2jk8gzy3n5e17-KLyCceDxCLe3xpC5RboA9K20nbjFGQkYovro5muIJHsBOOH6BvgwdN3lT8sLqt44fZ7f8FPz6cvm76pWfkLOrGebyEP_dy1lG-Qx21XMhqiMOIvSn5HPYbYHeY7284BnpMnuHZ32N_BuWCto607eD5MfSprPBBX_MAv-V3-fjEB8fngyLJLxbeB8f43nxwWqY4s0A763t7sqmqm7DOrbyR9px5HWtqrhYW0n-oP0Iecg-mO8pLLTZmjdr6iHgOW9G8Nj-H_bM-Ga1BQ_gPXsdBjBzKctgR6x_rJq7wOZC9AenTjb4vx09jEMbHw0VZ7Z-2K-ecqEkjvgU_LM9T7wI6Z34H8ojrLuwgr-1Mg7vGc9Z9GZedUq5HVocRfUAbXI8Yk-YJcUV_iPJc3R_Tb4zn4U-QUcnkIzk9lNtnbciggHwhz_Q6SVqFNjfws9qSj2lT1hE89LVyF4NCFtFTlP_3sOqvqcbKuMv1NAUb30OXmefqnII_N2A5a6p4k3kUeMmao79WDW7CeLTEWRr5WME6r6Le8zlyHPlgg_WZDsuXGasx9mWugWvlAsMQvPPwsB6h-kA5Up5v0OVJnIMy32L-Rr1OmrXytuwZ9A04_EjfnrMtPFeA3lNS2RbWmTQXbYV6xYgJRFfBKi9jvAVbYWdfLN9z8CAPMlup7x_Rj3Vvxu_WdzN4kNfa2Q8Xt7kc6J1oaXUT9Achn9BTxlyCtUy4_r-dvUA8WcFaLhQDICYq2e_xsO51GY9TzgF6-7oOZRE2TTVI5nzkk_ZF3tk5CdjWAb8P2Kvz0M0bJMxHpWugX-f7urX79shHP_XZT-OROfJunJOIPC979KUWu6n_wzgJeYLqr4XlCOgj8ByJepyozUDPLLdiPUk-nHzlGNlD1rSoO4MyAU0UN7bsnEGG-Fz7apnvObz_7j6f9eNhC31b1MyruIO1pmou2PvGPuCP6n24Xq32Qdvm98H9-X3YmY9qH-wHyh65fRyu9fj-8ivJ_bye7HYc74Bfbkd4td95RsYn3t_A1vFGCaGTfLwMLbBntuozbCm48-42XkPyxd1Zgv-U-e94HPKyOJmQS-7iGnhG-2MivRDNZD-MFXt0KAfq3iJNeC3WB8yifzQQV-zeYT_j2PvZ-UE8XWZdWrfwvpSqpjE6veaH_vysNqH67_DLpUj9QEMNnCXvRi4XE59gspuqBZoPXXbL_sqwxHzX8DrjfUWcY6CuQntpcW1sH-ZnTUAPu7cxTZmr6ujOo3OjTTOMrBWxmvWC7qwQR42epuQd82jczLud8FzKJ3YzqEI-lxYPKZ-Ku4-nE86uQx6SyLpLNfNuzN6mYFv_E-fB2qDhpmSXeB6wQ6R38S82wqcO61YYO0pp_jiQ14Zs1ncsjv6dBzfk26Ap3xtrClc1m0hYgjQXPGcy3w2UPPX52FpM6gD-Brfb5e5XrIjKPIL0LpXTdCrdjDSr7p0wPWSRv-CjUT1pU9rM-zUC4QEyyEF_uoHnp_e4j_X_Dw2dhyCF4ESaeOLTFPSf1L7JyW5oetdLDeB30dfATkB3ltBRu4q2aHcU_rg8oF4TvtjI_r78CvqNYFOG7ZuRy8Vx_Meoamc3behvi4cyI43wYdSywXkc5U8QRtlq4RdyF-rGHjzB_49vgch9VI6Z-ho9V5uv83XaEPYq3lf6Yrz_ieJ3kVzgvgbG3Ne9JDeQVzZPTpGJfaeVnFWeopWa8X-F2UlkOp7mk1QMai48jOTdHuMQdWXY3vaf9wfplxofIyxA7ypbCHnaitujfjEdd7ZS1BcRbOqLIGiPqeagHog9TnUFRfUM1BOStrp5In1nOQs8t2wt6azCjnQ3zJXJS1TfWt5bNYQ1Htkb7t_Ix-AvkJZIw6ilp60weo3qm4mz2HEfw_9oa8ALFUs6bJOLg3QJ7j4iHWIXlGjjrj7xkDH9z_vTkV6s6Wa-LsP-sc6vnpXBl7jvW5MjsrZD09f17Ln79V7Z91BPaqzG94WMW9fE_a99r9QHVOwfo8J-sQOlOpM9DAA3TLjlUnKdAjbp7ftTGMn-lneT6CYxD31fO5nhvpT96hPql66r7p09wYxnDubA_tUXVOBTFo2nHn61BDqftFh3MPeLaCc7dgH5tjfI_Y_LL1aK2GjnPBdo5COQhqSbJ7go3v7Wwy6V0iDtVaKfjW6H_prInv2zOfZ0382uWXOhsPn6J4xWDNR53Hf7bP8d_P9bq-f4L-HM8wqbeHHjTPYrXBEw8bOZ_OFTHHbltMI-j7SlWuTlrwHK2HBzTx51vtDCHzK76zc4iu9sI8z_oCjg_sDbF_XI5c_zht4kUf42Ja5Z12RoG5AvWbe4P8HJ67ZS0YY4bs71Xy1YitMJ_11kF31mMRp5WNc1A6D-ptg52Tavw3Ree2EWsrV4Sdoc3iGVAPG_0bq1-pVlP99wNroe6kcwn6nwDPH-ksJ2tP7vySztnZWTDYTS_nDvpYxtve1qBEbG69M9YKmNcSR38PXcHZTF8r_WHN55k8p3hL-ctvP3085n-RMO_8aSwXf0lX8frmqhGPdEbdBPEHfFJB3-f8IOdg3soaWD6FfYN88nzTsfKDjptn-ETWsf5Fjv8iNfKDeAl_gz2FWZpjHvgdzTlszfsB_Abyy6SbwQcPeCaC47hnP8-ParTNGm517cYgh8H_s0Aj_LPrZ_sPGP7-Vv337cXq9ms2vx8-fHnzotfCH8X-9X66XD68fDF--Lqc_PozxuIjD49eHj184R_c1kdv_jjSv8iO3rzCn8yO7D9kR296vJlM77bZ0ZvN1-305dF09ZDPh8UX_vNus9MdpuG_1M5Wd9OJDfvz5dHm9g4jZlx9x7WP_vwv
When the svg document contains a , (comma) inside, satori's regex greedily matches the group encodingType up to the last occurrence of ,. This results in incorrect parsing of encodingType and dataString.
not sure if that's the root case @kiwiyou, just tested out the preview URL in the PR and it doesn't seem to work: playground link
@steven-tey After some inspecting, it turns out that there are two problems in satori's image rendering process:
- Invalid parsing of plaintext data URI for svgs.
- Invalid caching of remote images.
The issue @fonstack reported seems to be the first case, which is explained and resolved, and this issue the other. Check #597 and #596 for the former.
The root cause of the second case is that satori clears the cache for image sizes on every invocation without clearing the cache for remote image fetching. The first invocation of satori actually does render the image well. But rendering with the same remote image URL again makes it assume that the image has already fetched and its size has been cached, only to fail because of the cleared cache. In the other words, it is not that images in SVG doesn't work when exported to PNG, but that images in SVG doesn't work when rendered again. Please correct me if I'm wrong.
Some reference:
- satori clearing the image size cache https://github.com/vercel/satori/blob/9bc47fd41937be1bc96db2c91420323d034bebef/src/satori.ts#L92-L93
- satori's global fetching cache https://github.com/vercel/satori/blob/9bc47fd41937be1bc96db2c91420323d034bebef/src/handler/image.ts#L65
- satori updating image size cache only on the first fetch https://github.com/vercel/satori/blob/9bc47fd41937be1bc96db2c91420323d034bebef/src/handler/image.ts#L226-L228 https://github.com/vercel/satori/blob/9bc47fd41937be1bc96db2c91420323d034bebef/src/handler/image.ts#L235-L271
Maybe the correct workaround is one of two:
- Clear the
inflightRequestscache on every invocation. - Update cache on early return based on
inflightRequestscache.
Hey @kiwiyou @steven-tey @Jackie1210 any update on this? I need this to be fixed in order to launch a product in production :)
@fonstack Your problem should be fixed in #596.
@fonstack Your problem should be fixed in #596.
thanks! any estimated time for the merge of the PR? @kiwiyou
I have neither privilege nor enough information for the estimation. Would you refer to the relevant issue #597 and PR #596, instead of this issue #592, and wait for the maintainer's response? Your problem doesn't seem to be directly related to this issue. (Check comment https://github.com/vercel/satori/issues/592#issuecomment-1979586066)
https://github.com/vercel/satori/issues/592#issuecomment-1979586066
The root cause of the second case is that satori clears the cache for image sizes on every invocation without clearing the cache for remote image fetching
It also leads to memory leak for each image being fetched by satori in our case. Maybe it's worth applying the configurable LRU cache here, or export the method to clear inflightRequests cache so that it can be cleared from the client code when it makes sense?
@kiwiyou @shuding
I found a workaround for this - all images need to be preloaded and added as base64 data to the content of rendered component.