Repo
Docs
Troubleshooting

Troubleshooting Runs

As with most tools, it can be frustrating to understand why Turborepo is not working the way you expect. This page covers some tools to debug when using the turbo CLI and some common problems you may encounter.

Enable Verbose Logs

The best debugging tool we have as developers are logs. You can turn up the log level with the --verbosity flag. Combined with building from source, this can be a powerful and flexible way to see what's going on under the hood.

Check the Run Summary

The --summarize flag generates and saves metadata about your turbo run as a JSON file in .turbo/runs. You can use it to compare subsequent runs, inspect the contents of the cached artifact, and the inputs to the hash for a task.

Check your Configuration

Task Configuration

You can get started with Turborepo with minimal configuration -- that's one of the things people love about Turborepo! But when you omit configuration, Turborepo internally falls back to smart defaults. Additionally, when using Workspace Configurations in a monorepo, it can be confusing to understand how Turborepo interpreted your turbo.json. You can use the --dry or --dry=json to get a "resolved" task configuration for any task. For example:

turbo run build --dry=json

Look for a resolvedTaskConfiguration key in the output.

User Config

When you link your repository to Vercel, Turborepo stores configuration in two places:

  • your Vercel team information is stored in .turbo/config.json. You can inspect this file to see what else might be in there!
  • an authentication token is stored in ~/Library/Application\ Support/turborepo/config.json.

Inspect the Cache

When turborepo runs a task that has configured outputs, it caches those outputs, along with the logs from that task in the node_modules/.cache/turbo/. These artifacts are compressed with tar, but you can uncompress and see what's in them.

Build from Source

One of the advantages of JavaScript codebases are that you can open up node_modules/ and edit the code you're running inline. This is not possible with turbo, because the runnable code is a compiled binary and you cannot edit it inline. But because the codebase is Open Source, you can always get the source code, modify it, and build it locally. The bulk of this documentation is available in the Contributing Guide (opens in a new tab), but you can use those directions even if you aren't planning to make a contribution.

  1. Clone the git repo from vercel/turbo (opens in a new tab)
  2. cd cli
  3. Make any changes (for example, add more logging)
  4. Run make
  5. From your project, use /:path/:to/:turbo/target/debug/turbo instead of global turbo or the version of turbo installed in your project.

Common Pitfalls

Nested workspaces

Turborepo does not support nested workspaces. Therefore, if you have a workspace that contains another workspace, you may see unexpected behavior. We recommend flattening your workspace structure to avoid this issue.

Root Dependencies

If you have a package defined in your monorepo that is used by several other packages in the monorepo, say a standard ESLint configuration, you may be tempted to list it as a root dependency by declaring it in the package.json at the root of your monorepo. This lets you use the dependency throughout your monorepo without having to declare it in each package's package.json. However, this can lead to unexpected cache hits, because Turbo does not include root internal dependencies, i.e. a dependency declared in your monorepo's package.json (root) that is implemented inside your monorepo (internal), in its cache signature. Therefore, if a root internal dependency changes, none of the other packages will get rebuilt.

To solve this, always explicitly add a package's internal dependencies to its package.json. You can find an explanation of how to do that here.

The .turbo directory

One of the core concepts behind Turbo is that when a declared input changes, the cached outputs for that task are invalidated. As part of running any task, Turborepo creates the following directories:

  • A .turbo at the root of your repo
  • A .turbo directory in each workspace if your project is a monorepo (e.g. apps/my-app/.turbo/)
  • A turbo directory in node_modules/.cache

Because the first two directories are not git-ignored by default, you may see an issue where you run the same task twice and get a cache missing, even though you didn't change anything, because the generated .turbo directories are getting included as the task inputs, and invalidating cache. To avoid this problem, add .turbo to your .gitignore file. Alternatively, you can also limit your inputs configuration so that .turbo is not included in the cache inputs.

Common Questions

I'm not seeing any cache hits

In general, you should expect that when you run turbo run twice in a row, you should get a cache hit on the second run. If this isn't happening, run both builds again with the --summarize flag and compare the generated Run Summaries to each other. In most cases, the comparison should show why the second run did not get a cache hit.

You can also ask:

I'm seeing cache hits, but my build is broken

My build is caching the wrong environment variables

Common Monorepo Questions

My dependency isn't being built correctly

  • Are you properly bundling and transpiling the dependency before building the application?

    For example, libraries like tsc, tsup, esbuild, babel, and swc will convert newer JavaScript features back to “pure” JavaScript.

    If you are using Next.js, you might be using transpilePackages. Ensure you add the name of the dependency inside next.config.js (example (opens in a new tab)).

  • Have you listed files in the dependency's package.json to point to the correct files?

My types are not being found

  • Did you specify types or typing inside the dependency's package.json to point to the .d.ts file?

  • Have you altered or set custom tsconfig.json paths?

    • Do they have the correct folder structure for your application?
    • Are they properly configured for the meta framework, bundler, or transpilation tool?