X
Xata•7mo ago
maxfi

Remix v2.8.1 (vite) on Vercel serverless function timeout when making xata db calls

The app is deploying properly and I can't see any issues in the runtime logs on Vercel. The serverless function (Node.js 20x) just timeouts after 60 seconds. Via console.logs I'm pretty sure it's related to a xata query. In the build logs I see the following warnings (not sure if this is related):
WARN: Failed to resolve dependency "kerberos"
WARN: Failed to resolve dependency "gcp-metadata"
WARN: Failed to resolve dependency "socks"
WARN: Failed to resolve dependency "snappy"
WARN: Failed to resolve dependency "aws4"
WARN: Failed to resolve dependency "mongodb-client-encryption"
WARN: Failed to resolve dependency "@mongodb-js/zstd"
WARN: Failed to resolve dependency "@aws-sdk/credential-providers"
WARN: Failed to resolve dependency "kerberos"
WARN: Failed to resolve dependency "gcp-metadata"
WARN: Failed to resolve dependency "socks"
WARN: Failed to resolve dependency "snappy"
WARN: Failed to resolve dependency "aws4"
WARN: Failed to resolve dependency "mongodb-client-encryption"
WARN: Failed to resolve dependency "@mongodb-js/zstd"
WARN: Failed to resolve dependency "@aws-sdk/credential-providers"
I've checked that process.env.XATA_API_KEY and process.env.XATA_BRANCH are defined in the serverless function (via console.log) and they are. I get the xata client like so: export const xata = getXataClient(); Potentiall other relavant parts of the Vercel build logs:
Vercel CLI 33.6.1
vite v5.1.6 building for production...
Vercel CLI 33.6.1
vite v5.1.6 building for production...
I'm using "@xata.io/client": "^0.29.3", in package.json. Any ideas how to further troubleshoot this? Thanks in advance!
19 Replies
kostas
kostas•7mo ago
Hello, have you checked the getting started guide? https://xata.io/docs/getting-started/remix Can you rule out if it's the Xata connection causing the timeout, by removing the Xata query (i.e. you can hardcode some fake results) and see if the app stops timing out? If it's proven to be the Xata query, can you provide a snippet of its code? Also, workspace/dbname and timestamp when the issue is triggered so we can check logs on our end might help to find out if it's a timeout on our end or something else.
maxfi
maxfi•7mo ago
Thanks for getting back to me @kostas. The strange thing is that prior to the refactor to remix, when this was a next.js app, the xata connection worked fine. That's what's got me thinking that it's something remix/vite/vercel related... I've created some test routes in my app: This route times out:
import { useLoaderData } from "@remix-run/react";
import type { LoaderFunctionArgs } from "@vercel/remix";
import { json } from "@vercel/remix";
import { xata } from "~/.server/xataDb.server";

export async function loader({ request }: LoaderFunctionArgs) {
const product = await xata.db.Products.select(["id"]).getFirstOrThrow();

return json({ product });
}

export default function TestProductRoute() {
const data = useLoaderData<typeof loader>();

return (
<div>
<h1>Test</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
import { useLoaderData } from "@remix-run/react";
import type { LoaderFunctionArgs } from "@vercel/remix";
import { json } from "@vercel/remix";
import { xata } from "~/.server/xataDb.server";

export async function loader({ request }: LoaderFunctionArgs) {
const product = await xata.db.Products.select(["id"]).getFirstOrThrow();

return json({ product });
}

export default function TestProductRoute() {
const data = useLoaderData<typeof loader>();

return (
<div>
<h1>Test</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
With the following error in the Vercel runtime logs:
Invoke Error {"errorType":"Error","errorMessage":"2024-03-20T15:51:31.791Z 4be19fea-381b-47d1-b490-876cd3849f04 Task timed out after 60.00 seconds","stack":["Error: 2024-03-20T15:51:31.791Z 4be19fea-381b-47d1-b490-876cd3849f04 Task timed out after 60.00 seconds"," at /opt/node-bridge/vercel-tla.js:9:1214"," at c (/opt/node-bridge/chunk-KFTOQFMY.js:1:7996)"," at Object.reject (/opt/node-bridge/chunk-KFTOQFMY.js:1:8455)"," at Timeout._onTimeout (/opt/node-bridge/vercel-tla.js:7:721)"," at listOnTimeout (node:internal/timers:573:17)"," at process.processTimers (node:internal/timers:514:7)"]}
Task timed out after 60.02 seconds
Invoke Error {"errorType":"Error","errorMessage":"2024-03-20T15:51:31.791Z 4be19fea-381b-47d1-b490-876cd3849f04 Task timed out after 60.00 seconds","stack":["Error: 2024-03-20T15:51:31.791Z 4be19fea-381b-47d1-b490-876cd3849f04 Task timed out after 60.00 seconds"," at /opt/node-bridge/vercel-tla.js:9:1214"," at c (/opt/node-bridge/chunk-KFTOQFMY.js:1:7996)"," at Object.reject (/opt/node-bridge/chunk-KFTOQFMY.js:1:8455)"," at Timeout._onTimeout (/opt/node-bridge/vercel-tla.js:7:721)"," at listOnTimeout (node:internal/timers:573:17)"," at process.processTimers (node:internal/timers:514:7)"]}
Task timed out after 60.02 seconds
However, looking at the Vercel Runtime Metrics, it says that the POST request to {{WORKSPACE}}.us-east-1.xata.sh/db/{{DB_NAME}}:{{BRANCH}}/tables/Products/query (I've redacted parts of the URL - I'll DM you these) was 200 OK in 277ms. As a side note, should this be faster, as the serverless function is also in Washington, D.C., USA (iad1)? This route works fine:
import { useLoaderData } from "@remix-run/react";
import type { LoaderFunctionArgs } from "@vercel/remix";
import { json } from "@vercel/remix";

export async function loader({ request }: LoaderFunctionArgs) {
const post = await fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => response.json())

return json({ post });
}

export default function TestFetchRoute() {
const data = useLoaderData<typeof loader>();

return (
<div>
<h1>Test</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
import { useLoaderData } from "@remix-run/react";
import type { LoaderFunctionArgs } from "@vercel/remix";
import { json } from "@vercel/remix";

export async function loader({ request }: LoaderFunctionArgs) {
const post = await fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => response.json())

return json({ post });
}

export default function TestFetchRoute() {
const data = useLoaderData<typeof loader>();

return (
<div>
<h1>Test</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
Here's an interesting thing, changing the route to use an edge function makes it work:
import { useLoaderData } from "@remix-run/react";
import type { LoaderFunctionArgs } from "@vercel/remix";
import { json } from "@vercel/remix";
import { xata } from "~/.server/xataDb.server";

export const config = { runtime: "edge" }; // <------ Use an edge function

export async function loader({ request }: LoaderFunctionArgs) {
const product = await xata.db.Products.select(["id"]).getFirstOrThrow();

return json({ product });
}

export default function TestProductRoute() {
const data = useLoaderData<typeof loader>();

return (
<div>
<h1>Test</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
import { useLoaderData } from "@remix-run/react";
import type { LoaderFunctionArgs } from "@vercel/remix";
import { json } from "@vercel/remix";
import { xata } from "~/.server/xataDb.server";

export const config = { runtime: "edge" }; // <------ Use an edge function

export async function loader({ request }: LoaderFunctionArgs) {
const product = await xata.db.Products.select(["id"]).getFirstOrThrow();

return json({ product });
}

export default function TestProductRoute() {
const data = useLoaderData<typeof loader>();

return (
<div>
<h1>Test</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
So it must be something related to the Node.js runtime on vercel? Running on Node.js 18.x on vercel I get the following error:
Unhandled Promise Rejection {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"TypeError: First parameter has member 'readable' that is not a ReadableStream.","reason":{"errorType":"TypeError","errorMessage":"First parameter has member 'readable' that is not a ReadableStream.","stack":["TypeError: First parameter has member 'readable' that is not a ReadableStream."," at assertReadableStream (/var/task/node_modules/.pnpm/web-streams-polyfill@3.3.3/node_modules/web-streams-polyfill/dist/ponyfill.js:466:19)"," at convertReadableWritablePair (/var/task/node_modules/.pnpm/web-streams-polyfill@3.3.3/node_modules/web-streams-polyfill/dist/ponyfill.js:4035:9)"," at ReadableStream.pipeThrough (/var/task/node_modules/.pnpm/web-streams-polyfill@3.3.3/node_modules/web-streams-polyfill/dist/ponyfill.js:4119:29)"," at fetchFinale (node:internal/deps/undici/undici:9905:56)"," at mainFetch (node:internal/deps/undici/undici:9794:9)"," at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: TypeError: First parameter has member 'readable' that is not a ReadableStream."," at process.<anonymous> (file:///var/runtime/index.mjs:1276:17)"," at process.emit (node:events:529:35)"," at emit (node:internal/process/promises:149:20)"," at processPromiseRejections (node:internal/process/promises:283:27)"," at process.processTicksAndRejections (node:internal/process/task_queues:96:32)"]}
Unhandled Promise Rejection {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"TypeError: First parameter has member 'readable' that is not a ReadableStream.","reason":{"errorType":"TypeError","errorMessage":"First parameter has member 'readable' that is not a ReadableStream.","stack":["TypeError: First parameter has member 'readable' that is not a ReadableStream."," at assertReadableStream (/var/task/node_modules/.pnpm/web-streams-polyfill@3.3.3/node_modules/web-streams-polyfill/dist/ponyfill.js:466:19)"," at convertReadableWritablePair (/var/task/node_modules/.pnpm/web-streams-polyfill@3.3.3/node_modules/web-streams-polyfill/dist/ponyfill.js:4035:9)"," at ReadableStream.pipeThrough (/var/task/node_modules/.pnpm/web-streams-polyfill@3.3.3/node_modules/web-streams-polyfill/dist/ponyfill.js:4119:29)"," at fetchFinale (node:internal/deps/undici/undici:9905:56)"," at mainFetch (node:internal/deps/undici/undici:9794:9)"," at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: TypeError: First parameter has member 'readable' that is not a ReadableStream."," at process.<anonymous> (file:///var/runtime/index.mjs:1276:17)"," at process.emit (node:events:529:35)"," at emit (node:internal/process/promises:149:20)"," at processPromiseRejections (node:internal/process/promises:283:27)"," at process.processTicksAndRejections (node:internal/process/task_queues:96:32)"]}
So I thought that maybe it was because the returned data wasn't serialized so I update the route code to:
import { useLoaderData } from "@remix-run/react";
import type { LoaderFunctionArgs } from "@vercel/remix";
import { json } from "@vercel/remix";
import { xata } from "~/.server/xataDb.server";

export async function loader({ request }: LoaderFunctionArgs) {
const product = await xata.db.Products.select(["id"]).getFirstOrThrow();
const serializedProduct = product.toSerializable();
console.log(serializedProduct);

return json({ serializedProduct });
}

export default function TestProductRoute() {
const data = useLoaderData<typeof loader>();

return (
<div>
<h1>Test</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
import { useLoaderData } from "@remix-run/react";
import type { LoaderFunctionArgs } from "@vercel/remix";
import { json } from "@vercel/remix";
import { xata } from "~/.server/xataDb.server";

export async function loader({ request }: LoaderFunctionArgs) {
const product = await xata.db.Products.select(["id"]).getFirstOrThrow();
const serializedProduct = product.toSerializable();
console.log(serializedProduct);

return json({ serializedProduct });
}

export default function TestProductRoute() {
const data = useLoaderData<typeof loader>();

return (
<div>
<h1>Test</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
I still get the TypeError: First parameter has member 'readable' that is not a ReadableStream. error. Also, the console.log(serializedProduct); isn't shown in the vercel runtimes logs. So I'm pretty sure it's something to do with the xata client unfortunately. Any ideas? Thanks!
maxfi
maxfi•7mo ago
GitHub
Two of the exact same commits deployed, one crashes, the other does...
Summary Running a Remix app on Vercel. I deployed a commit to production after upgrading some packages. It built fine but the serverless function swere crashing when you actually visit them. I used...
maxfi
maxfi•7mo ago
GitHub
ReadableStream type mismatch when deploying to Vercel · Issue #7547...
What version of Remix are you using? 2.0.1 Are all your remix dependencies & dev-dependencies using the same version? Yes Steps to Reproduce Fork the standard remix template and upgrade to v2 I...
maxfi
maxfi•7mo ago
GitHub
First parameter has member 'readable' that is not a ReadableStream ...
What version of Remix are you using? 2 and 1.19 Are all your remix dependencies & dev-dependencies using the same version? Yes Steps to Reproduce Start a new project using Remix Add @vercel/blo...
maxfi
maxfi•7mo ago
Still no joy unfortunately. I've tried removing the installGlobals call in my vite config but that's not made a difference.
maxfi
maxfi•7mo ago
GitHub
vercel/examples/remix/vite.config.ts at 7a28972897c031dcc247d3b7fae...
Develop. Preview. Ship. Contribute to vercel/vercel development by creating an account on GitHub.
kostas
kostas•7mo ago
Thanks for all your efforts to figure this out and make things work. I am wondering if it could have to do with the way the Xata client is initialized and then imported. Could you try initializing the xata client in the route itself like in the example here: https://github.com/xataio/examples/blob/main/apps/getting-started-remix/app/routes/posts.%24slug.tsx and see if that makes any difference? Import it directly from the client file import { getXataClient } from 'src/xata'; , then initialize it in the loader function const xata = getXataClient();
maxfi
maxfi•6mo ago
Thanks @kostas. I'll try that.
maxfi
maxfi•6mo ago
I'm pretty sure this is the issue: https://github.com/vercel/remix/issues/62
GitHub
First parameter has member 'readable' that is not a ReadableStream ...
Hi there, The Remix apps (mine and my customers') have stopped working quite out of the blue. Remix version: 2.0.1 to 2.1.0 Node: v18 This cannot be reproduced locally. See the below error: Unh...
maxfi
maxfi•6mo ago
Unfortunately this didn't work. The following works. 🥳
import { useLoaderData } from "@remix-run/react";
import type { LoaderFunctionArgs } from "@vercel/remix";
import { json } from "@vercel/remix";
import { XataClient } from "~/.server/xata.server";

export async function loader({ request }: LoaderFunctionArgs) {
const xata = new XataClient({
fetch: fetch, // Need to explicitly pass in fetch
});
const product = await xata.db.Products.select(["id"]).getFirstOrThrow();

return json({ product });
}

export default function TestProductRoute() {
const data = useLoaderData<typeof loader>();

return (
<div>
<h1>Test</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
import { useLoaderData } from "@remix-run/react";
import type { LoaderFunctionArgs } from "@vercel/remix";
import { json } from "@vercel/remix";
import { XataClient } from "~/.server/xata.server";

export async function loader({ request }: LoaderFunctionArgs) {
const xata = new XataClient({
fetch: fetch, // Need to explicitly pass in fetch
});
const product = await xata.db.Products.select(["id"]).getFirstOrThrow();

return json({ product });
}

export default function TestProductRoute() {
const data = useLoaderData<typeof loader>();

return (
<div>
<h1>Test</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
maxfi
maxfi•6mo ago
GitHub
client-ts/packages/client/src/util/fetch.ts at 655a9615349dab0e4b58...
Xata.io SDK for TypeScript and JavaScript. Contribute to xataio/client-ts development by creating an account on GitHub.
maxfi
maxfi•6mo ago
If I want to instantiate the xata client in a different file (ie, not in the loader), I need to do the following for it to work:
import { fetch as webFetch } from "@remix-run/web-fetch";
import { XataClient } from "./xata.server";

export const xata = new XataClient({
fetch: webFetch,
});
import { fetch as webFetch } from "@remix-run/web-fetch";
import { XataClient } from "./xata.server";

export const xata = new XataClient({
fetch: webFetch,
});
maxfi
maxfi•6mo ago
So it seems to be a weird fetch polyfill issue with remix on vercel. https://github.com/inngest/inngest-js/issues/304 Was really helpful!
GitHub
[BUG] unhandled promise rejected on remix with vercel · Issue #304 ...
Hello, I use inngest with remix and vercel and have successfull deployed my app but if I send data with inngest I get this: Unhandled Promise Rejection {"errorType":"Runtime.Unhandle...
maxfi
maxfi•6mo ago
It might be worth updating https://github.com/xataio/examples/tree/main/apps/getting-started-remix to the latest version of remix with vite to repro the issue
GitHub
examples/apps/getting-started-remix at main · xataio/examples
Your one-stop-shop to try Xata out. From packages to apps, whatever you need to get started. - xataio/examples
Want results from more Discord servers?
Add your server