Simplify your stack and build anything. Or everything.
Build tomorrowโ€™s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
Itโ€™s time to take back your content infrastructure.

Fetch failed during build on v3

default discord avatar
hristo6004last year
8

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't

cache 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] ]
  }
}


https://nextjs-faq.com/fetch-api-in-rsc

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.

  • default discord avatar
    errordude_404last year
    @415764121280184330

    I have cache enable but keep getting same error as you, any pointers to help me fix this issue?

  • default discord avatar
    hristo6004last year
    @527889407538364428

    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

    /api

    endpoints 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

  • default discord avatar
    errordude_404last year

    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.



    @415764121280184330
  • default discord avatar
    hristo6004last year

    I don't believe this is related to caching, does the collection exist? Can you share some code?

  • default discord avatar
    errordude_404last year

    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,
                            },
                        ],
                    },
    '

    @415764121280184330

    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",

  • default discord avatar
    hristo6004last year

    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-config

    is the config file in the root folder, I have it aliased ๐Ÿ˜

  • default discord avatar
    errordude_404last year
    @415764121280184330

    Thanks a ton that worked, I have the same alias as well

  • default discord avatar
    jakehopkinglast year

    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.


    @967118574445547650

    โ€” there's no workaround for this?

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.