GitHub Actions breaks Next.js build when API server unavailable during prerendering

I’m working on a Next.js app that connects to a Flask API backend for fetching data. Everything works perfectly on my local setup where both servers run together in Docker containers.

The problem happens when GitHub Actions tries to build my Next.js app. The build process fails because it can’t reach the Flask server during prerendering.

Here’s the build error I get:

> [email protected] build
> next build

   ▲ Next.js 15.3.3

   Creating an optimized production build ...
 ✓ Compiled successfully in 5.2s
 ✓ Linting and checking validity of types    
 ✓ Collecting page data    
Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
Error: getaddrinfo ENOTFOUND api-server
    at ClientRequest.emit (node:events:518:28)
    at Socket.socketErrorListener (node:_http_client:518:5)
    at Socket.emit (node:events:518:28)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
Export encountered an error on /page: /, exiting the build.
 ⨯ Next.js build worker exited with code: 1 and signal: null

The component causing issues:

/* PhotoGallery.tsx */

import fetch from 'node-fetch';
import PhotoCard from './PhotoCard';
import './PhotoGallery.css';

interface Photo {
  url: string,
  uid: number
};

export default async function PhotoGallery() {
  const apiUrl = 'http://api-server:5000';
  const result = await fetch(`${apiUrl}/photos/list`); // Fails here
  const photos: Photo[] = await result.json();

  return (
    <div className='photo-container'>
      {photos.map((photo) => 
        <PhotoCard imageUrl={photo.url} uid={photo.uid} key={photo.uid}/>
      )}
    </div>
  );  
};

I’ve tried making it a client component and using useEffect but the API call still happens during build time. I need help with either mocking the API for CI or preventing prerendering for this page.

been there with django backends. just wrap your fetch in try-catch and return an empty array or dummy data when it fails. also check if process.env.NODE_ENV === 'production' and skip the api call during build - return mock data for ci builds instead.

I’ve encountered this issue as well with a Next.js project that relies on an external API. The prerendering fails in GitHub Actions because the API server isn’t accessible during the build stage. To resolve this, consider adding export const dynamic = 'force-dynamic'; to your component. This setting will instruct Next.js to render the page on each request rather than during the build process. Additionally, it might be beneficial to implement a try-catch around the fetch logic, allowing you to handle cases when the API is down gracefully. Mocking data using environment variables to identify CI environments can also be a good approach if you don’t want to rely on live API calls during testing.

Your problem is Next.js trying to prerender when the API server doesn’t exist in CI. I hit the same issue with microservices where external dependencies weren’t available during builds. Easiest fix is adding error handling with fallback data right in your component. Update your PhotoGallery component to catch fetch errors and return empty state or skeleton data when the API’s unreachable. Build completes without needing environment-specific logic. Another option - move data fetching to a route handler in your app/api directory and call it from your component. Route handlers don’t run during build time, so no prerendering failures. Plus you get better control over error responses and caching.

you can also disable static generation for specific pages in next.config.js. just add generateStaticParams: false or set the page as dynamic in your config. this stops prerendering during build and completely avoids the api server issue.

Set up a conditional check with environment variables to detect CI runs and return mock data instead of hitting the API. In your GitHub Actions workflow, add CI=true, then modify your component to check for this variable. When it’s present, return hardcoded photo data that matches your Photo interface. Your build will complete without needing the Flask server running. I had the same issue with a Rails API backend and this approach worked perfectly. Build passes in CI, but everything works normally in dev and production where the API server’s available.