{"record":{"id":"77b87b70ed42a12b","repo":"vercel/turborepo","slug":"pnpm-workspace-parse-error","errorCode":"pnpm-workspace_parse_error","errorMessage":"failed to parse ${workspaceFile}","messagePattern":"failed to parse (.+?)","errorType":"exception","errorClass":"ConvertError","httpStatus":null,"severity":"error","filePath":"packages/turbo-workspaces/src/utils.ts","lineNumber":373,"sourceCode":"  workspaceFileName\n}: {\n  workspaceRoot: string;\n  workspaceFileName: string;\n}): Array<string> {\n  const workspaceFile = path.join(workspaceRoot, workspaceFileName);\n  if (existsSync(workspaceFile)) {\n    try {\n      const workspaceConfig = yaml.load(readFileSync(workspaceFile, \"utf8\"));\n      // validate it's the type we expect\n      if (\n        workspaceConfig instanceof Object &&\n        \"packages\" in workspaceConfig &&\n        Array.isArray(workspaceConfig.packages)\n      ) {\n        return workspaceConfig.packages as Array<string>;\n      }\n    } catch (err) {\n      throw new ConvertError(`failed to parse ${workspaceFile}`, {\n        type: \"pnpm-workspace_parse_error\"\n      });\n    }\n  }\n\n  return [];\n}\n\nfunction expandPaths({\n  root,\n  lockFile,\n  workspaceConfig\n}: {\n  root: string;\n  lockFile: string;\n  workspaceConfig?: string;\n}) {\n  const fromRoot = (p: string) => path.join(root, p);","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/vercel/turborepo/blob/f9245100cf0d31d96628804ead485f6bf226e55a/packages/turbo-workspaces/src/utils.ts#L355-L391","documentation":"When expanding pnpm workspace globs, utils reads pnpm-workspace.yaml with js-yaml; if yaml.load throws (a YAMLException such as bad indentation or duplicate keys), it becomes ConvertError `failed to parse <path>` with type pnpm-workspace_parse_error. Note that a syntactically valid file with the wrong shape (packages missing or not an array) does NOT throw here — the function silently returns [].","triggerScenarios":"pnpm-workspace.yaml containing tab characters for indentation, a malformed mapping, an unclosed quote, or duplicate keys; the file being hand-edited just before a workspace conversion reads it.","commonSituations":"Editors inserting tabs into YAML; pasting config from blog posts that mangle indentation; schema drift after a pnpm major version changes allowed keys.","solutions":["Run `pnpm install` in the repo — pnpm itself will report the exact YAML error location","Replace tab indentation with spaces and fix the flagged construct","Lint the file with any YAML validator, then rerun the conversion"],"exampleFix":"# before (tab indentation)\npackages:\n\t- \"apps/*\"\n\t- \"packages/*\"\n# after\npackages:\n  - \"apps/*\"\n  - \"packages/*\"","handlingStrategy":"validation","validationCode":"import { readFileSync, existsSync } from \"fs-extra\";\nimport yaml from \"js-yaml\";\nif (existsSync(workspaceFile)) {\n  try {\n    yaml.load(readFileSync(workspaceFile, \"utf8\"));\n  } catch (e) {\n    throw new Error(`pnpm-workspace.yaml is invalid: ${(e as Error).message}`);\n  }\n}","typeGuard":"function isConvertError(e: unknown): e is { type: string } {\n  return typeof e === \"object\" && e !== null && \"type\" in e;\n}","tryCatchPattern":"try {\n  await read(args);\n} catch (e) {\n  if (isConvertError(e) && e.type === \"pnpm-workspace_parse_error\") {\n    // run `pnpm install` to get pnpm's own error location, fix YAML, retry\n  } else {\n    throw e;\n  }\n}","preventionTips":["Use spaces (never tabs) when editing pnpm-workspace.yaml","Validate YAML in a pre-commit hook or editor lint after hand edits","Prefer letting `pnpm install` rewrite the workspace file over manual surgery"],"tags":["pnpm","yaml","parse-error","workspace"],"backgroundTag":"yaml-parse-error","analyzedSha":"f9245100cf0d31d96628804ead485f6bf226e55a","analyzedAt":"2026-08-17T10:46:15.696Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}