Handling 429 Too Many Requests Error with Google Gemini API in Next.js Client-Side Application

I’m encountering a 429 Too Many Requests error when using the @google/genai package to generate interview questions in a Next.js client-side application. The error persists despite implementing a retry mechanism, and it seems to be related to exceeding the free-tier quota limits for the Gemini 2.5 Pro model. Below is the relevant code and the error log.
The application is designed to generate interview questions using the Gemini 2.5 Pro model based on user input (job role, description, and experience). The withRetry function attempts to handle the 429 error with exponential backoff (5s, 10s, 20s), but it fails after three attempts. The error details indicate I’ve exceeded the free-tier quotas for daily tokens, daily requests, per-minute requests, and per-minute tokens.
my code:

GeminiAIModal.js:

import { GoogleGenAI } from '@google/genai';

    const apiKey = process.env.NEXT_PUBLIC_GEMINI_API_KEY;
if (!apiKey) {
    throw new Error('NEXT_PUBLIC_GEMINI_API_KEY is not set in environment variables');
}

const ai = new GoogleGenAI({ apiKey });
const config = {
    thinkingConfig: {
        thinkingBudget: -1, // Unlimited thinking budget as per your UI
    },
    responseMimeType: 'application/json', // Structured output
};
const model = 'gemini-2.5-pro';

async function withRetry(fn, maxRetries = 3, baseDelay = 5000) {
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
        try {
            return await fn();
        } catch (error) {
            if (error.message.includes('429') && attempt < maxRetries) {
                const delay = baseDelay * Math.pow(2, attempt - 1);
                console.log(`429 error, retrying after ${delay}ms (attempt ${attempt}/${maxRetries})`);
                await new Promise(resolve => setTimeout(resolve, delay));
                continue;
            }
            throw error;
        }
    }
}

export async function generateInterviewQuestions(prompt) {
    try {
        const result = await withRetry(async () => {
            const response = await ai.models.generateContentStream({
                model,
                config,
                contents: [
                    {
                        role: 'user',
                        parts: [{ text: prompt }],
                    },
                ],
            });
            let fullText = '';
            for await (const chunk of response) {
                fullText += chunk.text;
            }
            return fullText;
        });
        return JSON.parse(result);
    } catch (error) {
        console.error('Error in generateInterviewQuestions:', error);
        throw new Error('Failed to generate interview questions from Gemini API');
    }
}

AddCardWithDialog.jsx:

'use client';

import React, { useState } from 'react';
import { Dialog } from '@headlessui/react';
import { XMarkIcon } from '@heroicons/react/24/solid';
import { generateInterviewQuestions } from '../../utils/GeminiAIModal';

function AddCardWithDialog({ title, description }) {
    const [isOpen, setIsOpen] = useState(false);
    const [form, setForm] = useState({
        role: '',
        description: '',
        experience: '',
    });
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState(null);

    const handleStartInterview = async (e) => {
        e.preventDefault();
        setIsLoading(true);
        setError(null);

        const contents = `job position: ${form.role},
            job description: ${form.description},
            no of year experience: ${form.experience},
            depends of those info give me 5 interview qs in json format
            give qs and answers in json format`;

        try {
            const result = await generateInterviewQuestions(contents);
            console.log('Interview Questions:', result);
            setIsOpen(false);
        } catch (err) {
            console.error('Error generating questions:', err);
            setError('Failed to generate interview questions. Please try again.');
        } finally {
            setIsLoading(false);
        }
    };

    const handleChange = (e) => {
        setForm({ ...form, [e.target.name]: e.target.value });
    };

    return (
        <>
            <div
                onClick={() => setIsOpen(true)}
                className='p-10 border rounded-2xl bg-secondary hover:scale-105 hover:shadow-lg cursor-pointer transition-all'
            >
                <h2 className='text-lg text-center font-semibold text-gray-800'>{title}</h2>
            </div>

            <Dialog open={isOpen} onClose={() => setIsOpen(false)} className='relative z-50'>
                <div className='fixed inset-0 bg-black/30 backdrop-blur-sm' />

                <div className='fixed inset-0 flex items-center justify-center p-4'>
                    <Dialog.Panel className='relative w-full max-w-lg rounded-2xl bg-white p-6 shadow-xl'>
                        <button
                            onClick={() => setIsOpen(false)}
                            className='absolute top-4 right-4 text-gray-500 hover:text-red-600 transition-colors'
                        >
                            <XMarkIcon className='w-6 h-6' />
                        </button>

                        <Dialog.Title className='text-2xl font-bold text-gray-900 mb-1'>
                            Tell us more about Job you are interviewing
                        </Dialog.Title>
                        <Dialog.Description className='text-gray-500 mb-6'>
                            Add Details about job position, your skills and year of experience
                        </Dialog.Description>

                        <div className='space-y-4'>
                            <div>
                                <label className='block text-sm font-medium mb-1 text-gray-700'>
                                    Job Position / Role name
                                </label>
                                <input
                                    type='text'
                                    name='role'
                                    value={form.role}
                                    onChange={handleChange}
                                    className='w-full border rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500'
                                />
                            </div>

                            <div>
                                <label className='block text-sm font-medium mb-1 text-gray-700'>
                                    Job Description / Tech Stack in Short
                                </label>
                                <textarea
                                    name='description'
                                    rows={3}
                                    value={form.description}
                                    onChange={handleChange}
                                    className='w-full border rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 resize-none'
                                />
                            </div>

                            <div>
                                <label className='block text-sm font-medium mb-1 text-gray-700'>
                                    No of Year Experience
                                </label>
                                <input
                                    type='number'
                                    name='experience'
                                    value={form.experience}
                                    onChange={handleChange}
                                    className='w-full border rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500'
                                />
                            </div>
                        </div>

                        {error && (
                            <p className='mt-4 text-red-600 text-sm'>{error}</p>
                        )}

                        <div className='mt-6 flex justify-end space-x-3'>
                            <button
                                onClick={() => setIsOpen(false)}
                                className='px-4 py-2 rounded-md bg-gray-200 text-gray-600 hover:bg-gray-300'
                                disabled={isLoading}
                            >
                                Cancel
                            </button>
                            <button
                                onClick={handleStartInterview}
                                className='px-4 py-2 rounded-md bg-blue-600 text-white hover:bg-blue-700 disabled:bg-blue-400'
                                disabled={isLoading}
                            >
                                {isLoading ? 'Generating...' : 'Start Interview'}
                            </button>
                        </div>
                    </Dialog.Panel>
                </div>
            </Dialog>
        </>
    );
}

export default AddCardWithDialog;

the error log:

<project-path>utilsGeminiAIModal.js:24 429 error, retrying after 5000ms (attempt 1/3)
<project-path>utilsGeminiAIModal.js:36
POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:streamGenerateContent?alt=sse 429 (Too Many Requests)
[...stack trace...]
<project-path>utilsGeminiAIModal.js:24 429 error, retrying after 10000ms (attempt 2/3)
[...similar 429 error...]
<project-path>utilsGeminiAIModal.js:54  Error in generateInterviewQuestions: ClientError: got status: 429 . {"error":{"message":"{n  "error": {n    "code": 429,n    "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, head to: https://ai.google.dev/gemini-api/docs/rate-limits.",n    "status": "RESOURCE_EXHAUSTED",n    "details": [n      {n        "@type": "type.googleapis.com/google.rpc.QuotaFailure",n        "violations": [n          {n            "quotaMetric": "generativelanguage.googleapis.com/generate_content_free_tier_input_token_count",n            "quotaId": "GenerateContentInputTokensPerModelPerDay-FreeTier",n            "quotaDimensions": {n              "location": "global",n              "model": "gemini-2.5-pro"n            }n          },n          {n            "quotaMetric": "generativelanguage.googleapis.com/generate_content_free_tier_requests",n            "quotaId": "GenerateRequestsPerDayPerProjectPerModel-FreeTier",n            "quotaDimensions": {n              "model": "gemini-2.5-pro",n              "location": "global"n            }n          },n          {n            "quotaMetric": "generativelanguage.googleapis.com/generate_content_free_tier_requests",n            "quotaId": "GenerateRequestsPerMinutePerProjectPerModel-FreeTier",n            "quotaDimensions": {n              "model": "gemini-2.5-pro",n              "location": "global"n            }n          },n          {n            "quotaMetric": "generativelanguage.googleapis.com/generate_content_free_tier_input_token_count",n            "quotaId": "GenerateContentInputTokensPerModelPerMinute-FreeTier",n            "quotaDimensions": {n              "location": "global",n              "model": "gemini-2.5-pro"n            }n          }n        ]n      },n      {n        "@type": "type.googleapis.com/google.rpc.Help",n        "links": [n          {n            "description": "Learn more about Gemini API quotas",n            "url": "https://ai.google.dev/gemini-api/docs/rate-limits"n          }n        ]n      },n      {n        "@type": "type.googleapis.com/google.rpc.RetryInfo",n        "retryDelay": "49s"n      }n    ]n  }n}n","code":429,"status":""}}
    at throwErrorIfNotOK (<project-path>[email protected]:11201:1)
    [...stack trace...]
<project-path>componentsuiAddCardWithDialog.jsx:34  Error generating questions: Error: Failed to generate interview questions from Gemini API
    at generateInterviewQuestions (<project-path>utilsGeminiAIModal.js:55:15)
    [...stack trace...]

how can I work with the result I get from a post request I made in jquery

I receive a result from a post request i made to a server in json format as

  { name: 'Alice', grade: 95 },
  { name: 'Bob', grade: 80 },
  { name: 'Charlie', grade: 75 },

now when i try to display the whole result in my html it works out but when i try to grabe the data with the name eg.(grade), its not working please help me out

This what I try to access the name and the grade from the result

<script>
     var txt = "studentsdata";
    $.post("mydatasite.php", {listall: txt}, function(result){
      
const students = [result];

// Using forEach() with an anonymous function
students.forEach(function(student) {
  $(".allist").html(`${student.name} has a grade of ${student.grade}`);
});

});
</script>

but when i try to this code

<script>
     var txt = "studentsdata";
    $.post("mydatasite.php", {listall: txt}, function(result){
      
  $(".allist").html(result);

});
</script>

it show the data receiced in the html as

  { name: 'Alice', grade: 95 },
  { name: 'Bob', grade: 80 },
  { name: 'Charlie', grade: 75 },

in rxjs how can I make a new observable wait another observable before it continues?

Long story short, I have an async concurrency issue with an Authorization system.
I’m using rxjs to do these operations with observables.

In my application should be handled only one at a time that’s want to singIn, signUp or signOut. Any of these operations must wait there’s no currently one of the already running and if that the case they should wait in an ordered queue.

It all started with my signUp form, the function that handles this should register the account data in the credentials database and then write account data in the accounts database. These are two requests done one after another.

The library that handles authentication has an event that’s triggered after credentials are confirmed, which may happen before account data is written in the database.

Everything sum-up: I have a place that write data and the event that reads it but it does when it “feels like it”, I cannot change this. How do I make a variable to flag data being written and wait for it to finish before continuing?

I know exactly what I need here! A queue! Each request should be stacked and wait the previous one to complete before it continues. How do I make this in rxjs? How do I make an observable take place in a queue and wait another observable to finish?

My situation could be visualized like this with the following pseudo-code:

// this calls after signUpWithEmail and before writeDbData.
function onSignInEvent(userId): void {
    readDbData(userId).subscribe(); // access to db but signUp hasn't finished yet so gets nothing.
}

function signUp(email, password): Observable<Account> {
    
    return from(signUpWithEmail(email, password)).pipe(
        // here credentials registered and event should trigger.
        map(userId => createAccountData(userId)),
        switchMap(account => writeDbData(account)) // here is saved in db.
    );
}

Javascript array, finding duplicates then return the locations in new array;

I’am trying to build a function (preferably Javascript but JQuery is Ok) that searches through a vase array of exam results checking for duplicates scores. Using filter I have managed to return that the scores (2,4,5) have been achieved more than once.

    exam_scores[0] = [1, 2, 3, 7, 2, 4, 5, 4, 5, 7];
 
    // Returns exams_scores[0] That Are Duplicated;
    const duplicates = exams_scores[0].filter((item, index) => exams_scores[0].indexOf(item) !== index);
 
    console.log(duplicates); // Output: [2, 4, 5]`

From here (and this is what I am stuck on) I want to return a new two dimensional array with the indexes as they appear in the exam_scores array;

Thus in the example, it would return this:

result[0] = [1,4];  // 2 is found at index (1,4);
result[1] = [5,7];  // 4 is found at index (5,7);
result[2] = [6,8];  // 5 is found at index (6,8);

I know with the few lines of code thus far I could use a for – loop but this will have over 1500 names.

I have looked at filter but not sure what is the best was to go about it.

Thanks.

    exam = [1, 2, 3, 7, 2, 4, 5, 4, 5, 7];
    
    // Returns Numbers That Are Duplicated;
    const duplicates = exam.filter((item, index) => exam.indexOf(item) !== index);
    console.log(duplicates+"<br/>"); // Output: [2, 4, 5]
 
    // I then want to return the index of each duplication in a new array as outlined above.

Is this object created only once or every time I import it?

Since I’m having a bug that I can’t figure out, a cold doubt has assailed me:.

I have the below code in a Svelte 5 SvelteKit app.

And I’m importing import { queryClient } from './src/query.ts from multiple places in my big and complex app.

Doing so am I recreating queryClient each time I import it?

Or is it creating it only one time per app lifecycle?

Is there a way to call it just one time per lifecycle of the app?

  • ./src/query.ts:
export const queryClient = new QueryClient({
    defaultOptions: {
        // options here
    }
});

How to get all the matches for a repeated group in a RegExp in JavaScript?

I try to parse the expression in a <svg><path d="expression" /></svg> element. I want to do transformations of the points in JavaScript.

My first step is to parse the path expression. I tought doing this with a RegExp (see below). The code I doesn’t behave as I expected. It only finds the last occurence of each group. What is the best way to make this work? Is it possible with Regexp? If this is the only way regexp can behave in JavaScript, I suppose I have to match a first regex, then do the rest of the parsing with normal JavaScript. But I would like to first know if it’s possible with another RegExp based code. I’d like to learn to use Regexp’s better.


let path = `M4,24
    L4,23
    Q12,23,12, 9
    L14, 9
    C15, 3,25, 3,26,9
    L28,9
    Q28,23,36,23
    L36,24
    Z`

// This function does is dysfunctional
function parsePath(path) {
    // To simplify the match RegExp, I simplify the path string first:
    //    All comma's and all whitespace characters are simplified to a simple separator space.
    let path2 = path.replaceAll(/[,s]+/g, ' ')
    let rgx = /([A-Za-z])(?:(d+)s+)*/g
    
    let matches = [...path2.matchAll(rgx)].map(x => {
        return [x[1], x.slice(2)] 
    })

    return matches
}

console.log(parsePath(path))
// OUTPUT:
[
  [ 'M', [ '24' ] ],
  [ 'L', [ '23' ] ],
  [ 'Q', [ '9' ] ],
  [ 'L', [ '9' ] ],
  [ 'C', [ '9' ] ],
  [ 'L', [ '9' ] ],
  [ 'Q', [ '23' ] ],
  [ 'L', [ '24' ] ],
  [ 'Z', [ undefined ] ]
]
// EXPECTED AND DESIRED OUTPUT:
[
  [ 'M', [ '4', '24' ] ],
  [ 'L', [ '4', '23' ] ],
  [ 'Q', [ '12', '23', '12', '9' ] ],
  // ...
]

Video frames shake/stutter when rendering HTML5 video to Canvas during CSS animation

Video frames shake/stutter when rendering HTML5 video to Canvas during CSS animation

I’m experiencing video frame shaking/stuttering in a video carousel where videos are rendered to Canvas while a CSS animation is running. The videos should play smoothly but instead show visual jitter and frame drops.

Setup

I have a video carousel that:

  • Uses HTML5 <video> elements with Canvas rendering via drawImage()
  • Runs a continuous CSS animation (transform: translateY())
  • Uses IntersectionObserver to control video playback
  • Renders video frames using requestAnimationFrame

The Problem

Videos shake/stutter when the carousel animation is running. When I disable the CSS animation, videos play smoothly.

Relevant Code

Canvas Video Rendering:

function setupCanvasVideoPlayer(container, video) {
    const canvas = document.createElement('canvas');
    canvas.className = 'video-canvas';
    container.appendChild(canvas);
    
    const ctx = canvas.getContext('2d');
    ctx.imageSmoothingEnabled = false;
    
    let animationId;
    let isPlaying = false;
    
    const renderFrame = () => {
        if (!container.isConnected || !isPlaying) return;
        
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        try {
            ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
        } catch (e) {
            // Handle drawing errors
        }
        animationId = requestAnimationFrame(renderFrame);
    };
    
    video.addEventListener('play', () => {
        isPlaying = true;
        if (!animationId) {
            animationId = requestAnimationFrame(renderFrame);
        }
    });
}

CSS Animation:

.carousel-track {
    animation: scrollVideos 20s linear infinite;
    will-change: transform;
    backface-visibility: hidden;
    transform: translateZ(0);
}

@keyframes scrollVideos {
    0% { transform: translateY(0); }
    100% { transform: translateY(-1760px); }
}

HTML Structure:

<div class="right-carousel">
    <div class="carousel-track">
        <div class="carousel-video">
            <video src="video1.mp4" autoplay muted playsinline></video>
        </div>
        <div class="carousel-video">
            <video src="video2.mp4" autoplay muted playsinline></video>
        </div>
        <!-- More videos... -->
    </div>
</div>

What I’ve Tried

  1. GPU Acceleration optimizations:

    will-change: transform;
    backface-visibility: hidden;
    transform: translateZ(0);
    
  2. Canvas optimizations:

    ctx.imageSmoothingEnabled = false;
    // Using requestAnimationFrame for rendering
    
  3. Video element positioning:

    video.style.visibility = 'hidden';
    video.style.position = 'absolute';
    video.style.pointerEvents = 'none';
    

Questions

  1. Why does the CSS animation cause Canvas video rendering to shake?
  2. How can I synchronize Canvas rendering with CSS animations?
  3. Are there better approaches for smooth video playback in animated containers?
  4. Should I use transform3d() instead of translateY() for better performance?

Browser Testing

  • Chrome: Severe shaking
  • Firefox: Moderate shaking
  • Safari: Used Fallback Image

Expected Result

Smooth video playback without frame drops or visual stuttering during carousel animation.

Actual Result

Videos appear to shake/stutter, creating a poor user experience.


Environment:

  • Modern browsers (Chrome 120+, Firefox 115+)
  • Video format: MP4
  • Canvas 2D context
  • CSS animations + requestAnimationFrame

Any insights on resolving this Canvas + CSS animation conflict would be greatly appreciated!

Passing down a react context in tanstack router in react vite with js

I’m trying to pass a React context (auth) to my routes using TanStack Router, but I keep getting this error:
Uncaught TypeError: rootRoute.addChildren is not a function

I defined my context and wrapped my app like this:

This is the app.jsx:


   import { AuthProvider, useAuth } from "./context/auth/auth.jsx";
   import { router } from "./router/routes.jsx";
   import { RouterProvider } from "@tanstack/react-router";

   function App() {
     return (
      <AuthProvider>
       <InnerApp />
     </AuthProvider>
    );
   }
   function InnerApp() {
     const auth = useAuth();

      return <RouterProvider router={router} context={{ auth }} />;
   }

   export default App;

   

this is the routes.jsx for defined the router


   import {
     Router,
     Outlet,
     createRoute,
     redirect,
     createRootRouteWithContext,
   } from "@tanstack/react-router";
   import HomePage from "../pages/HomePage";
   import LoginPage from "../pages/LoginPage";

   const rootRoute = createRootRouteWithContext({
     component: () => (
       <>
         <Outlet />
       </>
      ),
   });

   const indexRoute = createRoute({
     getParentRoute: () => rootRoute,
     path: "/",
     component: HomePage,
   });

  const loginRoute = createRoute({
    getParentRoute: () => rootRoute,
    path: "/login",
    component: LoginPage,
    beforeLoad: ({ context }) => {
      const authctx = context.auth;
      const { role, isLoggedIn } = authctx();
      if (isLoggedIn && role == "user") {
        throw redirect({ to: "/" });
      }
      if (isLoggedIn && role == "admin") {
        throw redirect({ to: "/admin" });
      }
      return;
  },
  });

  const routeTree = rootRoute.addChildren([
    indexRoute,
    loginRoute,
  ]);

  export const router = new Router({
    routeTree,
   context:{
    auth:undefined
    }
  });


when i create just rootRoute it all works well without an error

Scraping IDs from two pages behind a login

So I need some help getting ID’s from page sources. They are tables that contain links.

<table id="running_freeleech" class="items_table">   
    <tr class="colhead">
        <td colspan="2">Currently Running Freeleech</td>
        <td>Ends in</td>
    </tr>
    <tr class="group_torrent row_a">
        <td class="center cats_col">
            <div title="Adventure"class="cats_games tags_adventure windows"></div>
        </td>
    <td>
    <span id="groupplatform">
        <a href="artist.php?artistname=Windows">Windows</a></span> -<a href='page.php?id=696969' title='View File'>(title)                  
    </td>
  </tr>
<a href='page.php?id=12345'>Link</a> <!- This is the ID I need. I can put them into an array for the next step.  -->
</table>
<table>

<!-- First ID I need is in the LINK : example 696969 --->

<!-- The seond page I need to grab two IDs ---> 


<table>
    <tbody id="edition_1">
        <tr class="group_torrent" style="font-weight: normal;" id="torrent09876">
            <td>
                <span>[<a href="torrents.phpaction=download&amp;id=NEEDTHISID&amp;authkey=NEEDTHISAUTHKEY&amp;torrent_pass=torrentpass" title="Download">DL</a>FILES<strong class="freeleech_label">Freeleech!</strong>]</a></span>
            </td>
        </tr>
    </tbody>
</table>    
 
 

I can build the URL with that data and automate it. The problem is that it is a private site and I don’t know how ot automate logging in. But I can manually login if that’s how I have to do it. I figure I can use jQuery to search through elements but I need a little push in the right direction. I’ve tried a couple things but I haven’t coded for years so I am out of practice..

Is there a way to add data to the URL hash while browser is refreshing?

I’ve got a page with some accordions and other dynamic content and want to properly preserve the user’s scroll position when they refresh the page. (Otherwise the browser autoscrolls back to “where they were” which is actually a random other position when the accordions aren’t opened back up yet.)

So I figured I would save the state to the URL hash on refresh, something like:

history.scrollRestoration = "manual";

document.addEventListener("beforeunload", function () {
  var elIdx = myCodeToFindCurrentElementIndex();
  //window.location.hash += "_SCROLL=" + elIdx;
  history.replaceState(null, "", window.location.hash + "_SCROLL=" + elIdx);
  console.log("unload:", window.location.href);
}, false);

console.log("initial:", window.location.href);
myCodeToScrollToElementWithIndex(+location.hash.split("_SCROLL=")[1])

This does log the new _SCROLL= as part of the URL it sees during the unload handling, and I even see it blink in the toolbar momentarily. But then the initial (i.e. new) location.href seen as the refreshed Javascript starts back up again is missing the late addition. And so it doesn’t get the element index it was expecting to scroll back to.

I’ve tried similar via the visibilitychange event and that didn’t seem to improve the situation either. If I push/replace history navigation state earlier it does persist across refresh, but it seems maybe the browser already has in mind the URL which will be refreshed to by the time these events fire.

Is this a correct understanding of what’s happening? Is there any way to make persistent changes to the history/location.hash like this in a way that would let me “tuck data away” in the URL while the page is refreshing?

“callbackSuccess is not a function” error when running async typescript

I have a runner I’m working on. Here is the part of the code that executes the script:

eval(`(async (api) => {
            try {
                ${script}
            } catch (error) {
                console.error(error);
            }
        })(api,);`);

api is defined elsewhere in the code.
When I run an API call like this:

api.call(
      "Get",
      {
        "typeName": "TYPENAME",
          "fromDate": "2025-06-11T04:00:00.000Z",
          "toDate": "2025-06-12T03:59:59.000Z",

        }
      }
    );

I get the following error:
callbackSuccess is not a function TypeError: callbackSuccess is not a function

I was expecting the results of the call to populate. for some api calls, it works and the results populate. There is seemingly no reason some calls work; some calls requesting large amounts of data are fine and some requesting small amounts of data don’t work.

I found a solution but it’s not a permanent solution. IF you add a success callback (or a promise), it prints the data.

   api.call(
      "Get",
      {
        "typeName": "TYPENAME",
          "fromDate": "2025-06-11T04:00:00.000Z",
          "toDate": "2025-06-12T03:59:59.000Z",
        }
      }
      , function(data) {
        console.log(data);
      }
    );

This solution isn’t great as it requires the user to add the callback. is there any way to fix this in the eval code that executes the script? Thanks

Modify the clipboard contents of rich formatted html like tables, while maintaining formatting and structure

I’d like to be able to modify the clipboard data of specific elements while maintaining the original structure the clipboard data would’ve been had it not been modified.

For instance, when copying a row in the table below, the html data within the clipboard is valid with parent <table> and <tbody> tags, but also only includes <trow> for selected rows. Maintaining this formatting while modifying specific elements of the clipboard data is what I’m looking for.

A header Another header
{replace} row
Second row

However, it looks like there’s no way to obtain the clipboard data that would be copied if you hijack the copy event with document.addEventListener('copy', copyHandler), and prevent the default copy event. Unless I’m incorrect, it seems the selection data and writing to the clipboard must be done manually. Getting the selection data can be handled using window.getSelection().getRangeAt(n), and retrieving selected html elements from that would contain incomplete fragments such as <tr> or <td>.

Is there a good way to then generically get the necessary contextual HTML elements to wrap the selected fragment for writing back into the clipboard data, like the default clipboard behavior? I’d like this to work for any of the incomplete tags like <li>, <td>, or just standalone selected tags

Problem rendering fullscreen/fixed canvas in iOS safari

I’m rendering multiple WebGL “scenes” with one context using a single canvas element that is fullscreen and with a fixed position

The page contains several div elements and I use their positions to define scissor regions on the main canvas, to render different scenes into each div’s space

This works fine on desktop but on iOS safari I have this behavior: the canvases are lagging behind, acting weird:

enter image description here

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title></title>
    <style type="text/css">
    #main-canvas{
        position: fixed;
        top: 0;
        left: 0;
        pointer-events: none;
        z-index: 9999;
    }
    .canvas{
        width: 700px;
        height: 500px;
        border: 1px solid black;
    }
    </style>
</head>
<body>
<canvas id="main-canvas"></canvas>
<div class="canvas" id="canvas-1"></div><br><br>
<div class="canvas" id="canvas-2"></div><br><br>
<div class="canvas" id="canvas-3"></div><br><br>
<div class="canvas" id="canvas-4"></div><br><br>

<script type="text/javascript">
let main_canvas = document.getElementById("main-canvas");

function resize_event(){
    main_canvas.width = window.innerWidth;
    main_canvas.height = window.innerHeight;
}
resize_event();
window.addEventListener("resize", () => resize_event());

let gl = main_canvas.getContext("webgl2");

let colors = [
    [1, 0, 0, 1],
    [0, 1, 0, 1],
    [0, 0, 1, 1],
    [1, 1, 0, 1] 
];

function update(){
    gl.enable(gl.SCISSOR_TEST);
    gl.viewport(0, 0, main_canvas.width, main_canvas.height);
    gl.clearColor(0, 0, 0, 0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    let main_canvas_rect = gl.canvas.getBoundingClientRect();

    for (let i = 1; i <= 4; i++) {
        let canvas = document.getElementById("canvas-" + i);
        let rect = canvas.getBoundingClientRect();

        gl.scissor( 
            rect.left,
            main_canvas_rect.height - rect.top - rect.height,
            rect.width,
            rect.height);
        gl.viewport(
            rect.left,
            main_canvas_rect.height - rect.top - rect.height,
            rect.width,
            rect.height);
    
        gl.clearColor(
            colors[i - 1][0],
            colors[i - 1][1],
            colors[i - 1][2],
            colors[i - 1][3]);
        gl.clear(gl.COLOR_BUFFER_BIT);
    }

    requestAnimationFrame(update);
}
requestAnimationFrame(update);

</script>
</body>
</html>

Next.js and Jest: TypeError `the “original” argument must be of type function`

I am new to Next.js but not to React and Jest; this is the first test suite I’m setting up in Next.js.

I have the following (extremely minimal, but this example does cause the error) component I am trying to test:

export default function Thumbnail(src){
  return(
    <img src={src}/>
  );
};

And the following test that is causing an error:

import { render } from '@testing-library/react';

import Thumbnail from './Thumbnail';


describe('Thumbnail', () => {

  test('renders ImageThumbnail for images', () => {
    render(
      <Thumbnail src='test.jpg' />
    );
  });
});

The error in question is this:

  ● Test suite failed to run

    TypeError: The "original" argument must be of type function. Received an instance of Object

       5 |
       6 | describe('Thumbnail', () => {
    >  7 |
         | ^
       8 |   test('renders ImageThumbnail for images', () => {
       9 |     render(
      10 |       <Thumbnail src='test' />

      at Object.<anonymous> (node_modules/test-exclude/index.js:5:14)
      at Module.call [as require] (node_modules/next/src/server/require-hook.ts:70:26)
      at Object.<anonymous> (node_modules/babel-plugin-istanbul/lib/index.js:12:43)
      at Module.call [as require] (node_modules/next/src/server/require-hook.ts:70:26)
      at _babelPluginIstanbul (node_modules/@jest/transform/build/index.js:52:39)
      at ScriptTransformer._instrumentFile (node_modules/@jest/transform/build/index.js:313:18)
      at ScriptTransformer._buildTransformResult (node_modules/@jest/transform/build/index.js:376:33)
      at ScriptTransformer.transformSource (node_modules/@jest/transform/build/index.js:431:17)
      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/index.js:519:40)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/index.js:558:19)
      at Object.<anonymous> (src/app/Thumbnail.test.js:7:59)

I started with, as you might imagine, a somewhat more interesting and complex component and ambitions for a test suite, but simplified down to this point in an attempt to track down the error. Evidently, the issue is not with my particular component. I have also tried rendering a normal HTML img tag in the test, that works just fine, so Jest and React Testing Library are doing their jobs just fine. The error message is infuriatingly vague and gets shadowed over in google results by errors with unrelated packages.

Suggestions on what else to try to resolve this error (given that I’m out of component and test code to simplify) or where to find documentation on this would be extremely appreciated.