nextjs - 💡(How to fix) Fix Build - Debug file tracing with `--turbopack` [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#84959Fetched 2026-04-08 02:17:54
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
0
Author
Timeline (top)
labeled ×2closed ×1commented ×1issue_type_added ×1

Error Message

console.error('Error while tracing files:', err); console.error('fs not available in this context. First 20 traced files:'); console.error(out.slice(0, 20).map(o => ${o.file} -> ${o.types}).join('\n')); try { console.error('Failed to write nft debug:', e && e.stack ? e.stack : String(e)); } catch (_) {}

Root Cause

Lambda are too big in my current setup so I can not deploy on Vercel. (A Serverless Function has exceeded the unzipped maximum size of 250 MB.) Locally I tried to debug the issue with npx next build --turbopack Looking at *.js.nft.json files I can see this is because file tracing includes the full repository for certain pages.ts files.

Fix Action

Fix / Workaround

TLDR: File tracing issues are not debuggeable

  • no out-of-the-box solution
  • using @vercel/nft directly does not give the same ouput as a real build
  • patching node_modules does not raise immediatly the answer

And I also tried to patch node_modules\next\dist\compiled\@vercel\nft\index.js so that I can see in real condition what is going on.

I added the following code to patch nodeFileTrace

Code Example

{
  "version": 1,
  "files": [
    "../../../../../../Makefile",
    "../../../../../../README.md",
    "../../../../../../components.json",
...
    "../../../../chunks/ssr/src_messages_fr_json_3c6a9a9a._.js",
    "./page/react-loadable-manifest.json",
    "./page_client-reference-manifest.js"
  ]
}

---

#!/usr/bin/env node
import { nodeFileTrace } from '@vercel/nft';
import path from 'path';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

function printStack(file, reasons, stdout, cwd, depth = 0) {
  const indent = '  '.repeat(depth);
  stdout.push(`${indent}${file}`);

  const reason = reasons.get(file);

  if (
    !reason ||
    !reason.parents ||
    (reason.type.length === 1 &&
      reason.type.includes('initial') &&
      reason.parents.size === 0)
  ) {
    return;
  }

  // Show why this file was included
  const types = Array.from(reason.type).join(', ');
  stdout.push(`${indent}  └─ Reason: ${types}`);

  for (let parent of reason.parents) {
    printStack(parent, reasons, stdout, cwd, depth + 1);
  }
}

async function main() {
  const files = [
    path.join(__dirname, '.next/server/app/[locale]/PATH_TO_MY_PAGE/page.js'),
  ];

  console.log(`Tracing files:\n${files.join('\n')}\n`);

  try {
    const { fileList, reasons } = await nodeFileTrace(files, {
      base: process.cwd(),
      processCwd: process.cwd(),
      mixedModules: true,
      conditions: ['node', 'import', 'require', 'default', 'module', 'production'],
      ignore: [
        '**/*.map',
        '**/node_modules/.bin/**',
        '**/.next/cache/**',
        '**/next/dist/**',
      ],
      exportsOnly: true,
    });

    console.log('Traced files with dependency chains:');
    console.log('=====================================\n');

    for (const file of fileList) {
      console.log(`📁 ${file}`);
      const stack = [];
      printStack(file, reasons, stack, process.cwd());

      // Remove the first line since we already printed the file name
      stack.shift();

      if (stack.length > 0) {
        console.log('Dependencies:');
        console.log(stack.join('\n'));
      } else {
        console.log('  └─ Entry point (no dependencies)');
      }
      console.log('');
    }

    console.log(`Total: ${fileList.size} files`);
  } catch (err) {
    console.error('Error while tracing files:', err);
    process.exit(1);
  }
}

main();

---

const s = {
  fileList: r.fileList,
  esmFileList: r.esmFileList,
  reasons: r.reasons,
  warnings: r.warnings,
};

const path = (() => {
  try { return require('path'); } catch (_) { return eval('require')('path'); }
})();

let fs;
try {
  // Prefer normal require when available
  if (typeof require === 'function') {
    fs = require('fs');
  } else {
    // Fallback to eval('require') which avoids static analysis by bundlers
    fs = eval('require')('fs');
  }
} catch (err) {
  // Last-ditch async fallback if running in ESM async context
  try {
    // This requires the surrounding function to be async. Use only if safe.
    // const mod = await import('fs'); fs = mod.default || mod;
    fs = null;
  } catch (e) {
    fs = null;
  }
}

try {
  const out = []; // build your 'out' array earlier as before
  for (const file of r.fileList) {
    const reason = r.reasons.get(file);
    const types = reason ? Array.from(reason.type).join(', ') : '(no reason)';
    const parents = reason && reason.parents ? Array.from(reason.parents) : [];
    out.push({ file, types, parents });
  }

  if (fs) {
    const outFile = path.join(process.cwd(), '.next', 'nft-debug.json');
    // ensure dir exists
    try { fs.mkdirSync(path.dirname(outFile), { recursive: true }); } catch (_) {}
    fs.writeFileSync(outFile, JSON.stringify(out, null, 2));
    console.log('NFT debug written to:', outFile);
  } else {
    // If fs is not available, emit a small signal to the console with summary info
    // Avoid printing the entire trace to stdout to prevent blocking
    console.error('fs not available in this context. First 20 traced files:');
    console.error(out.slice(0, 20).map(o => `${o.file} -> ${o.types}`).join('\n'));
  }
} catch (e) {
  try { console.error('Failed to write nft debug:', e && e.stack ? e.stack : String(e)); } catch (_) {}
}
  return s;
}

---

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Pro
  Available memory (MB): 16093
  Available CPU cores: 16
Binaries:
  Node: 22.20.0
  npm: 11.6.2
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 15.5.5 // Latest available version is detected (15.5.5).
  eslint-config-next: 15.5.5
  react: 19.2.0
  react-dom: 19.2.0
  typescript: 5.9.3
Next.js Config:
  output: N/A
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/vercel/next.js

To Reproduce

Try to debug a file tracing issue.

Current vs. Expected behavior

TLDR: File tracing issues are not debuggeable

  • no out-of-the-box solution
  • using @vercel/nft directly does not give the same ouput as a real build
  • patching node_modules does not raise immediatly the answer

Hello,

Lambda are too big in my current setup so I can not deploy on Vercel. (A Serverless Function has exceeded the unzipped maximum size of 250 MB.) Locally I tried to debug the issue with npx next build --turbopack Looking at *.js.nft.json files I can see this is because file tracing includes the full repository for certain pages.ts files.

Such a file look like

{
  "version": 1,
  "files": [
    "../../../../../../Makefile",
    "../../../../../../README.md",
    "../../../../../../components.json",
...
    "../../../../chunks/ssr/src_messages_fr_json_3c6a9a9a._.js",
    "./page/react-loadable-manifest.json",
    "./page_client-reference-manifest.js"
  ]
}

I would not expect the full root of my repository to be included in here after review. I discovered there is a reasons object in nodeFileTrace. However I do not succeed to output this.

I tried both to use directly @vercel/nft with this script

#!/usr/bin/env node
import { nodeFileTrace } from '@vercel/nft';
import path from 'path';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

function printStack(file, reasons, stdout, cwd, depth = 0) {
  const indent = '  '.repeat(depth);
  stdout.push(`${indent}${file}`);

  const reason = reasons.get(file);

  if (
    !reason ||
    !reason.parents ||
    (reason.type.length === 1 &&
      reason.type.includes('initial') &&
      reason.parents.size === 0)
  ) {
    return;
  }

  // Show why this file was included
  const types = Array.from(reason.type).join(', ');
  stdout.push(`${indent}  └─ Reason: ${types}`);

  for (let parent of reason.parents) {
    printStack(parent, reasons, stdout, cwd, depth + 1);
  }
}

async function main() {
  const files = [
    path.join(__dirname, '.next/server/app/[locale]/PATH_TO_MY_PAGE/page.js'),
  ];

  console.log(`Tracing files:\n${files.join('\n')}\n`);

  try {
    const { fileList, reasons } = await nodeFileTrace(files, {
      base: process.cwd(),
      processCwd: process.cwd(),
      mixedModules: true,
      conditions: ['node', 'import', 'require', 'default', 'module', 'production'],
      ignore: [
        '**/*.map',
        '**/node_modules/.bin/**',
        '**/.next/cache/**',
        '**/next/dist/**',
      ],
      exportsOnly: true,
    });

    console.log('Traced files with dependency chains:');
    console.log('=====================================\n');

    for (const file of fileList) {
      console.log(`📁 ${file}`);
      const stack = [];
      printStack(file, reasons, stack, process.cwd());

      // Remove the first line since we already printed the file name
      stack.shift();

      if (stack.length > 0) {
        console.log('Dependencies:');
        console.log(stack.join('\n'));
      } else {
        console.log('  └─ Entry point (no dependencies)');
      }
      console.log('');
    }

    console.log(`Total: ${fileList.size} files`);
  } catch (err) {
    console.error('Error while tracing files:', err);
    process.exit(1);
  }
}

main();

But this traced much less files so I suspect it does not reproduce real build conditions.

And I also tried to patch node_modules\next\dist\compiled\@vercel\nft\index.js so that I can see in real condition what is going on.

I added the following code to patch nodeFileTrace

const s = {
  fileList: r.fileList,
  esmFileList: r.esmFileList,
  reasons: r.reasons,
  warnings: r.warnings,
};

const path = (() => {
  try { return require('path'); } catch (_) { return eval('require')('path'); }
})();

let fs;
try {
  // Prefer normal require when available
  if (typeof require === 'function') {
    fs = require('fs');
  } else {
    // Fallback to eval('require') which avoids static analysis by bundlers
    fs = eval('require')('fs');
  }
} catch (err) {
  // Last-ditch async fallback if running in ESM async context
  try {
    // This requires the surrounding function to be async. Use only if safe.
    // const mod = await import('fs'); fs = mod.default || mod;
    fs = null;
  } catch (e) {
    fs = null;
  }
}

try {
  const out = []; // build your 'out' array earlier as before
  for (const file of r.fileList) {
    const reason = r.reasons.get(file);
    const types = reason ? Array.from(reason.type).join(', ') : '(no reason)';
    const parents = reason && reason.parents ? Array.from(reason.parents) : [];
    out.push({ file, types, parents });
  }

  if (fs) {
    const outFile = path.join(process.cwd(), '.next', 'nft-debug.json');
    // ensure dir exists
    try { fs.mkdirSync(path.dirname(outFile), { recursive: true }); } catch (_) {}
    fs.writeFileSync(outFile, JSON.stringify(out, null, 2));
    console.log('NFT debug written to:', outFile);
  } else {
    // If fs is not available, emit a small signal to the console with summary info
    // Avoid printing the entire trace to stdout to prevent blocking
    console.error('fs not available in this context. First 20 traced files:');
    console.error(out.slice(0, 20).map(o => `${o.file} -> ${o.types}`).join('\n'));
  }
} catch (e) {
  try { console.error('Failed to write nft debug:', e && e.stack ? e.stack : String(e)); } catch (_) {}
}
  return s;
}

But for a reason I fail to understand only node_modules stuff is in the output.

There is either

  • a bug in file tracing
  • or in my setup but I can not say which for sure as I can not investigate.

Can you help me find a way out please ? If it is do-able with the current setup If not what should we implement to have the right debugging info ? I would be happy to write the documentation to unlock other users if that is all that is missing

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Pro
  Available memory (MB): 16093
  Available CPU cores: 16
Binaries:
  Node: 22.20.0
  npm: 11.6.2
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 15.5.5 // Latest available version is detected (15.5.5).
  eslint-config-next: 15.5.5
  react: 19.2.0
  react-dom: 19.2.0
  typescript: 5.9.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Turbopack

Which stage(s) are affected? (Select all that apply)

Vercel (Deployed), next build (local)

Additional context

No response

extent analysis

TL;DR

To resolve the issue with file tracing in Next.js, modify the nodeFileTrace function to output the reasons object for further debugging.

Guidance

  1. Verify file tracing configuration: Ensure that the nodeFileTrace function is correctly configured to include the necessary files and dependencies.
  2. Check the reasons object: Inspect the reasons object to understand why certain files are being included in the tracing output.
  3. Modify the nodeFileTrace function: Update the function to output the reasons object for each file, allowing for further debugging and analysis.
  4. Test with a minimal setup: Create a minimal reproduction of the issue to isolate the problem and test potential solutions.

Example

const { nodeFileTrace } = require('@vercel/nft');

// ...

const { fileList, reasons } = await nodeFileTrace(files, {
  // ...
});

// Output the reasons object for each file
for (const file of fileList) {
  const reason = reasons.get(file);
  console.log(`File: ${file}, Reason: ${reason.type.join(', ')}`);
}

Notes

The issue may be related to the configuration of the nodeFileTrace function or the specific setup of the Next.js project. Further debugging and analysis are necessary to determine the root cause.

Recommendation

Apply a workaround by modifying the nodeFileTrace function to output the reasons object, allowing for further debugging and analysis. This will provide more insight into why certain files are being included in the tracing output.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING