Hi guys,
On v3, how should I fix the following error, when I try to build, I get a lot of fetch failed errors and that's (I'm only guessing) because I'm trying to fetch from an API that is not yet live.
I'm still predominantly using GraphQL and fetching from
/api/graphql/. I don't plan on switching completely yet to the Local API.
This is basically how I fetch and
fetchDocs()is from the website template and that's fetching from GraphQL:
// ...
let jobs: Job[] = []
try {
jobs = await fetchDocs<Job>('jobs', {
...props,
})
} catch (error) {
console.error(error)
}
if (jobs.length === 0) {
return <EmptyBlock text="No Jobs Found ๐ข" />
}
return ...I do get the pages generated after all, but I'd like to get rid of these errors. Should I start an instance of the server separately, so during build it can be fetched? And if so, how should I set it up so it does it automatically, for example when I send it over to Hetzner + Coolify? Or there's a better way?
Thank you. ๐
Oh. I now remembered that Nextjs 15
doesn'tcache by default, so adding a
cache: 'force-cache'to the
fetchDocs()function fixed it. ๐
Today I tried to build again and apparently my 'fix' above hasn't fixed it (it never did make sense in the first place, to be honest).
So I started getting the same errors during build:
Collecting page data
Generating static pages (1/7) [= ]TypeError: fetch failed
at node:internal/deps/undici/undici:12502:13
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async w (D:\dev\schooljob-payload-v3\.next\server\app\(app)\page.js:356:475)
at async S (D:\dev\schooljob-payload-v3\.next\server\app\(app)\page.js:356:2657) {
[cause]: AggregateError [ECONNREFUSED]:
at internalConnectMultiple (node:net:1117:18)
at afterConnectMultiple (node:net:1684:7)
at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
code: 'ECONNREFUSED',
[errors]: [ [Error], [Error] ]
}
}So logically, fetching from my own API routes is an anti-pattern and I should instead access the information directly without going through the HTTP layer.
Which leaves me with the only option to use the Local API when it comes to fetching server-side.
Switching to Local API fixed the fetching issue, but it's sad that I had to let go of GraphQL.
I have cache enable but keep getting same error as you, any pointers to help me fix this issue?
as far as I understand, if you're using caching and need to build, you should be using Local API, because you can't reach your
/apiendpoints with regular REST API/GraphQL since they're not built yet
on v2 it was possible, because during build you were building first the payload app on express, running it (which exposes the API) and then building the frontend app, which can now reach the API endpoints to grab the data and generate the needed files for build, hopefully it makes sense and someone fix me if I"m wrong
Thanks for the super fast response, and I belive you are right there is "payload build" command for this very reason and I tried using local api, but it says "a collection with the slug <slugname-that-i-had-set> does not exist" did you have similar issues by any change? Or did you possibily do some intermiediate step I may have failed to do?
The collection with slug Pages can't be found. Find Operation.this is the exact error when doing a find op.
I don't believe this is related to caching, does the collection exist? Can you share some code?
This is what is fetching the page data for each page
/*
* Copyright (c) All right reserved Anvish Inc. 2024
* This project and any portion thereof may not be reproduced or used in any manner without the express written permission of Anvish Inc.
*/
import React from "react";
import qs from "qs";
import payload from "payload";
interface FetchPageDataProps {
slug: string;
}
export const FetchPageData: React.FC<FetchPageDataProps> = async ({ slug }) => {
// Check if the environment is build or runtime
const isBuildEnv = process.env.NEXT_PUBLIC_BUILD_ENV === "true";
if (isBuildEnv) {
// Using Payload Local API during build process
try {
const result = await payload.find({
collection: "pages", // Specify your collection name here
where: {
slug: {
equals: slug,
},
},
limit: 1,
depth: 2,
});
if (result.docs.length > 0) {
return result.docs[0];
} else {
return null;
}
} catch (err) {
console.log(err, "error");
return null;
}
} else {
// Using HTTP API during runtime
const queryString = qs.stringify({
where: {
slug: {
equals: slug,
},
},
limit: 1,
depth: 2,
});
try {
console.log(
"fetch url",
`${process.env.NEXT_PUBLIC_PAYLOAD_URL}/api/pages?${queryString}`
);
let data: any = await fetch(
`${process.env.NEXT_PUBLIC_PAYLOAD_URL}/api/pages?${queryString}`,
{
method: "GET",
next: {
revalidate: Number(process.env.CACHE_VALIDITY_TIME) || 0,
tags: ["server-wide"],
},
}
);
data = await data.json();
if (data?.docs?.length > 0) {
return data.docs[0];
} else {
return null;
}
} catch (err) {
console.log(err, "error");
return null;
}
}
};This is the collection I am trying to fetch
import {CollectionConfig} from "payload/types";
const Pages: CollectionConfig = {
slug: "pages",
admin: {
useAsTitle: "page_name",
},
access: {
read: () => true, // Allow public read access
},
fields: [
{
name: "page_name",
type: "text",
required: true,
label: "Page Name",
admin: {
position: "sidebar",
},
},
{
name: "slug",
type: "text",
required: true,
unique: true,
label: "Slug",
admin: {
position: "sidebar",
},
},
{
name: "content",
type: "blocks",
blocks: [
{
slug: "text",
labels: {
singular: "Text",
plural: "Texts",
},
fields: [
{
name: "text",
type: "text",
required: true,
},
],
},
'The collection is quite long so I cut it off for reference
this is the build script
"build": "cross-env NEXT_PUBLIC_BUILD_ENV=true next build",
That's not the way to fetch with the Local API.
You should import these
import configPromise from '@payload-config'
import { getPayloadHMR } from '@payloadcms/next/utilities'then use it like so
const payload = await getPayloadHMR({
config: configPromise,
})
const data = await payload.find({
collection: 'pages',
...
})@payload-configis the config file in the root folder, I have it aliased ๐
Thanks a ton that worked, I have the same alias as well
Thanks for sharing this
@415764121280184330โ I understand the issue, and it's obvious now that you highlight it: I can't fetch from my API that hasn't been built yet. Really irritating. I've spent quite some time writing GQL queries that now have no value.
โ there's no workaround for this?
Star
Discord
online
Get dedicated engineering support directly from the Payload team.