{"record":{"id":"c075d5f881f8eacf","repo":"vercel/turborepo","slug":"cannot-infer-turbo-version-due-to-use-of-catalog","errorCode":null,"errorMessage":"Cannot infer turbo version due to use of `catalog` protocol. Remove `turbo` from your PNPM catalog to ensure correct turbo version is used","messagePattern":"Cannot infer turbo version due to use of `catalog` protocol\\. Remove `turbo` from your PNPM catalog to ensure correct turbo version is used","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/turbo-ignore/src/get-turbo-version.ts","lineNumber":30,"sourceCode":"  let { turboVersion } = args;\n  if (turboVersion) {\n    info(`Using turbo version \"${turboVersion}\" from arguments`);\n    return turboVersion;\n  }\n\n  const packageJsonPath = path.join(root, \"package.json\");\n  try {\n    const raw = fs.readFileSync(packageJsonPath, \"utf8\");\n    const packageJson = JSON.parse(raw) as PackageJson;\n    const dependencies = packageJson.dependencies?.turbo;\n    const devDependencies = packageJson.devDependencies?.turbo;\n    turboVersion = dependencies || devDependencies;\n    if (turboVersion !== undefined) {\n      if (!turboVersion.startsWith(\"catalog:\")) {\n        info(`Inferred turbo version \"${turboVersion}\" from \"package.json\"`);\n        return turboVersion;\n      }\n      warn(\n        \"Cannot infer turbo version due to use of `catalog` protocol. Remove `turbo` from your PNPM catalog to ensure correct turbo version is used\"\n      );\n    }\n  } catch (e) {\n    error(\n      `\"${packageJsonPath}\" could not be read. turbo-ignore turbo version inference failed`\n    );\n    return null;\n  }\n\n  const turboJSONPath = path.join(root, \"turbo.json\");\n  try {\n    const rawTurboJson = fs.readFileSync(turboJSONPath, \"utf8\");\n    const turboJson: { tasks?: unknown; pipeline?: unknown } =\n      JSON5Parse(rawTurboJson);\n    if (\"tasks\" in turboJson) {\n      info(`Inferred turbo version ^2 based on \"tasks\" in \"turbo.json\"`);\n      return \"^2\";","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/vercel/turborepo/blob/f9245100cf0d31d96628804ead485f6bf226e55a/packages/turbo-ignore/src/get-turbo-version.ts#L12-L48","documentation":"turbo-ignore tailors its affected-check to the workspace's turbo version and first tries to infer it from `dependencies.turbo` / `devDependencies.turbo` in package.json. A `catalog:` specifier (the pnpm catalog protocol) cannot be resolved to a concrete version from that file alone, so turbo-ignore warns, abandons this inference source, and falls through to the next ones (turbo.json's `turbo` field, then defaults).","triggerScenarios":"package.json contains `\"turbo\": \"catalog:\"` or `catalog:<name>` under dependencies/devDependencies, and turbo-ignore runs for that directory (VERCEL build step or CI script), hitting the startsWith('catalog:') branch.","commonSituations":"Monorepos that adopted pnpm catalogs for all internal dependency versions; turbo-ignore then runs with a default/fallback version instead of the cataloged one, potentially mismatching behavior.","solutions":["Replace the catalog reference for turbo with an explicit version range in that package.json (as the warning instructs)","Ensure turbo.json declares its `\"turbo\"` version so the fallback inference finds a real value","Migrate the check from turbo-ignore to `turbo query affected`, since turbo-ignore is deprecated anyway"],"exampleFix":"// before: package.json\n\"devDependencies\": { \"turbo\": \"catalog:\" }\n\n// after: package.json\n\"devDependencies\": { \"turbo\": \"^2.3.3\" }","handlingStrategy":"type-guard","validationCode":"import fs from 'node:fs';\n\nconst pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));\nconst spec = pkg.dependencies?.turbo ?? pkg.devDependencies?.turbo;\nif (typeof spec === 'string' && spec.startsWith('catalog:')) {\n  throw new Error('turbo-ignore cannot resolve catalog: specifiers — pin a version');\n}","typeGuard":"type CatalogSpecifier = `catalog:${string}`;\n\nfunction isCatalogSpecifier(spec: string): spec is CatalogSpecifier {\n  return spec.startsWith('catalog:');\n}","tryCatchPattern":null,"preventionTips":["Keep turbo's version pinned directly in the workspace that turbo-ignore inspects","Alternatively maintain the `turbo` version field in turbo.json as the fallback inference source","Plan migration to `turbo query affected` — the entire turbo-ignore command is deprecated"],"tags":["turbo-ignore","pnpm","catalog","version-inference"],"backgroundTag":"unresolvable-version-specifier","analyzedSha":"f9245100cf0d31d96628804ead485f6bf226e55a","analyzedAt":"2026-08-17T10:46:15.696Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}