vercel/turborepo · error · TransformError

Unable to write package.json

Error message

Unable to write package.json

What it means

Thrown by create-turbo's official-starter transform when it cannot write the modified starter package.json back to disk. The transform mutates the starter's package.json (sets the project name for the basic example, pins the bundled turbo version) and persists it with fs.writeJsonSync; any failure of that write raises this non-fatal TransformError.

Source

Thrown at packages/create-turbo/src/transforms/official-starter.ts:84

      if (packageJsonContent.devDependencies?.turbo) {
        // if the user specified a turbo version, use that
        if (opts.turboVersion) {
          packageJsonContent.devDependencies.turbo = opts.turboVersion;
          // use the same version as the create-turbo invocation
        } else {
          // eslint-disable-next-line @typescript-eslint/no-var-requires -- Have to go get package.json
          const version = (require("../../package.json") as { version: string })
            .version;
          packageJsonContent.devDependencies.turbo = `^${version}`;
        }
      }

      try {
        fs.writeJsonSync(rootPackageJsonPath, packageJsonContent, {
          spaces: 2
        });
      } catch (err) {
        throw new TransformError("Unable to write package.json", {
          transform: meta.name,
          fatal: false
        });
      }
    }
  }

  return { result: "success", metaJson, ...meta };
}

View on GitHub (pinned to 9f94a7d215)

Solutions

  1. Ensure the target directory is writable (`chmod u+w <dir>` / run under $HOME) and re-run create-turbo
  2. Close editors and pause cloud-sync/antivirus for the scaffold directory, then retry
  3. Check free disk space (`df -h .`) and retry
  4. If the scaffold otherwise completed, fix it manually: open the created package.json and set `name` and `devDependencies.turbo` yourself

Example fix

# before
npx create-turbo@latest my-app   # fails while OneDrive locks package.json
# after
# pause sync (or scaffold outside the synced folder), then:
npx create-turbo@latest my-app
Defensive patterns

Strategy: try-catch

Validate before calling

import fs from 'node:fs';

function canWriteFile(p: string): boolean {
  try {
    fs.accessSync(fs.dirname ?? fsConstants(p), fs.constants.W_OK);
    return true;
  } catch {
    return false;
  }
}
// simpler: fs.accessSync(projectRoot, fs.constants.W_OK) before invoking create-turbo

Try / catch

try {
  await createApp({ root });
} catch (err) {
  if (err instanceof TransformError && err.fatal === false && /package\.json/.test(err.message)) {
    // recover manually: apply the two mutations yourself (project name + turbo version)
    const pkg = JSON.parse(fs.readFileSync(`${root}/package.json`, 'utf8'));
    pkg.devDependencies ??= {};
    pkg.devDependencies.turbo = `^${installedTurboVersion}`;
    fs.writeFileSync(`${root}/package.json`, JSON.stringify(pkg, null, 2));
  } else throw err;
}

Prevention

When it happens

Trigger: fs.writeJsonSync(rootPackageJsonPath, packageJsonContent, { spaces: 2 }) throwing: EACCES/EROFS on the project root, ENOSPC, or EPERM because the file is locked by antivirus, an editor, or a sync client (typical on Windows).

Common situations: Scaffolding into an unwritable or read-only directory; OneDrive/Dropbox locking package.json as it syncs; endpoint protection scanning files the moment they are written; CI workspace mounted read-only.

Related errors


AI-assisted analysis of vercel/turborepo@9f94a7d215 (2026-08-16). Data as JSON: /api/errors/248968f1778b9a19. Report an issue: GitHub.