Nx.js & next.js build error, can't find a user config at /var/task/next-i18next.config.js

In a package-based next.js project based on nx.js, I encountered the following error:

next-i18next was unable to find a user config at /var/task/next-i18next.config.js

The project directory structure is as follows:

.
├── dist    # packages/web build output dir
├── nx.json
├── package-lock.json
├── package.json
├── packages
  ├── hooks # hooks library
  ├── icons # icons library
  ├── web   # next.js web app
    ├── babel.config.json
    ├── configs
    ├── next-env.d.ts
    ├── next-i18next.config.js
    ├── next.config.js
    ├── package.json
    ├── pages
    ├── project.json
    ├── public
    ├── styles
    ├── theme
    ├── tsconfig.json
    ├── scripts
    └── tsconfig.base.json
  • nx.js: 15.8.9
  • next.js: 13.1.1
  • node: 18.12.1

The scripts section in the package.json file in the root directory is as follows:

{
  "scripts": {
    "dev": "nx run web:serve --development --verbose",
    "build": "nx run web:build --production --verbose && node ./scripts/copyFiles.js"
  }
}

The project.json file for the web application in nx is configured as follows:

{
  "name": "web",
  "$schema": "../../node_modules/nx/schemas/project-schema.json",
  "sourceRoot": "packages/web",
  "projectType": "application",
  "targets": {
    "build": {
      "executor": "@nrwl/next:build",
      "outputs": [
        "{options.outputPath}"
      ],
      "defaultConfiguration": "production",
      "options": {
        "root": "packages/web"
      },
      "configurations": {
        "development": {
          "outputPath": "dist/web"
        },
        "production": {
          "outputPath": "dist/web"
        },
        "staging": {
          "outputPath": "dist/web"
        },
        "beta": {
          "outputPath": "dist/web"
        }
      }
    },
    "export": {
      "executor": "@nrwl/next:export",
      "options": {
        "buildTarget": "web:build:production"
      }
    }
  }
}

next-i18next.config.js:

const configs = require('./configs');
const locales = Object.keys(configs.languages);
const path = require('path');

const isDev = process.env.NODE_ENV === 'development';
const isProd = process.env.NODE_ENV === 'production';

const getLocalePath = () => {
    if (isProd) {
        return path.resolve('./public/locales');
    }

    if (isDev) {
        return configs.isServer
            ? require('path').resolve('./packages/web/public/locales')
            : '/locales';
    }

    return path.resolve('./public/locales');
};

module.exports = {
    // debug: isDev,
    i18n: {
        localeDetection: false,
        defaultLocale: 'en',
        locales,
    },
    defaultNS: 'common',
    lowerCaseLng: true,
    localePath: getLocalePath(),
    nsSeparator: '::',
    keySeparator: '::',
    reloadOnPrerender: true,
    // Do not load a fallbakick.  We'll just use the key as the fallback.
    fallbackLng: false,
    // Empty strings should be invalid, so we can fallback to the message key
    returnEmptyString: false,
};

next.config.js:

const {withNx} = require('@nrwl/next/plugins/with-nx');
process.env.I18NEXT_DEFAULT_CONFIG_PATH = `${__dirname}/next-i18next.config.js`;
const {i18n} = require('./next-i18next.config');
const path = require('path');
const configs = require('./configs');

/**
 * @type {import('@nrwl/next/plugins/with-nx').WithNxOptions}
 **/
const nextConfig = {
    i18n,
    nx: {
        svgr: false,
    },
    rewrites: async () => [
        {
            source: '/api/:path*',
            destination: `${configs.env.endpoints.baseAPI}/api/:path*`, // Proxy to Backend
        },
    ],
    transpilePackages: ['@crownbit/icons'],
    experimental: {
        largePageDataBytes: 1000 * 1000,
    },
    useFileSystemPublicRoutes: true,
    reactStrictMode: true,
    env: {
        MOON_ENV: process.env.NX_MOON_ENV,
        LATEST_GIT_HASH: process.env.LATEST_GIT_HASH,
    },
    sentry: {},
};

const {withSentryConfig} = require('@sentry/nextjs');

async function withCustom(phase) {
    const nxConfig = withNx(nextConfig);
    const c = await nxConfig(phase);
    return withSentryConfig(
        c,
        {
            silent: true,
            project: 'javascript-nextjs',
        },
        {
            widenClientFileUpload: true,

            transpileClientSDK: true,

            tunnelRoute: '/monitoring',

            hideSourceMaps: true,

            disableLogger: true,
        },
    );
}

module.exports = withCustom;

Because nx cannot output the build files in the source directory, the output directory for the web project is set to the
dist directory in the root directory. However, nx does not copy the next-i18next.config.js and configs directories to
the dist directory. Therefore, I wrote a script to copy the next-i18next.config.js and configs directories to the dist
directory:

const fs = require('fs-extra');

function copyFileOrDirectory(source, destination) {
    try {
        fs.copySync(source, destination);
        console.log(`${source} Copy successful!`);
    } catch (err) {
        console.error(`${source} Copy failed:`, err);
    }
}

console.log('Preparing to copy file or directory');
copyFileOrDirectory('./packages/web/configs', './dist/web/configs');

copyFileOrDirectory(
    './packages/web/next-i18next.config.js',
    './dist/web/next-i18next.config.js',
);

process.exit(0);

This script works correctly on the local development environment and self-managed servers. However, when deploying to Netlify, I encountered the following error:

next-i18next was unable to find a user config at /var/task/next-i18next.config.js

Does anyone know about this issue? Are there any recommended solutions?

Maybe try including that file in functions manually: How to Include Files in Netlify Serverless Functions?

I added the netlify.toml file to the root of the project and configured it as follows:

# Include all files in all functions
[functions]
  included_files = ["packages/web/configs/**", "packages/web/next-i18next.config.js"]

but it doesn’t work properly and the online environment still reports errors, is there any other solution?

Sorry for the delay. Is it possible for you to share a minimal repo so we can check the issue?

hi,hrishikesh,thank you very much for your reply.

I rebuilt a minimal repo: GitHub - onejustone/web

and netlify preview link: https://main--flourishing-khapse-9514a8.netlify.app/

Please help us with the deployment process as soon as possible and we will consider using the Enterprise version.

Hey @groot,

Thank you for that repo, that was super helpful! I was able to try some changes and also made some progress, but still not enough to get the site working. So I have asked the devs to take a look and comment what kind of a configuration can get this working.

OK, I’m waiting for your reply, hopefully we can get a grip.