{"record":{"id":"1b350d288288f7ac","repo":"pnpm/pnpm","slug":"filter-changed","errorCode":"FILTER_CHANGED","errorMessage":"Filtering by changed packages failed. ${'stderr' in err ? err.stderr as string : ''}","messagePattern":"Filtering by changed packages failed\\. (.+?)","errorType":"exception","errorClass":"PnpmError","httpStatus":null,"severity":"error","filePath":"pnpm11/workspace/projects-filter/src/getChangedProjects.ts","lineNumber":80,"sourceCode":"\nasync function getChangedDirsSinceCommit (commit: string, workingDir: string, testPattern: string[], changedFilesIgnorePattern: string[]): Promise<ChangedDir[]> {\n  let diff!: string\n  try {\n    diff = (\n      await execa('git', [\n        'diff',\n        '--name-only',\n        // Keeps an option-like `<since>` (`--output=...`) from being\n        // parsed as a git option — git rejects it as a bad revision.\n        '--end-of-options',\n        commit,\n        '--',\n        workingDir,\n      ], { cwd: workingDir })\n    ).stdout as string\n  } catch (err: unknown) {\n    assert(util.types.isNativeError(err))\n    throw new PnpmError('FILTER_CHANGED', `Filtering by changed packages failed. ${'stderr' in err ? err.stderr as string : ''}`)\n  }\n  const changedDirs = new Map<string, ChangeType>()\n\n  if (!diff) {\n    return []\n  }\n\n  const allChangedFiles = diff.split('\\n')\n    // The prefix and suffix '\"' are appended to the Korean path\n    .map(line => line.replace(/^\"/, '').replace(/\"$/, ''))\n  const patterns = changedFilesIgnorePattern.filter(\n    (pattern) => pattern.length\n  )\n  const changedFiles = (patterns.length > 0)\n    ? micromatch.default.not(allChangedFiles, patterns, {\n      dot: true,\n    })\n    : allChangedFiles","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/pnpm/pnpm/blob/6261b7f388016d57ca6b90340342411cd1d0d00f/pnpm11/workspace/projects-filter/src/getChangedProjects.ts#L62-L98","documentation":"Changed-package filtering (pnpm11/workspace/projects-filter/src/getChangedProjects.ts:80) shells out to `git diff --name-only --end-of-options <commit> -- <workingDir>` to list files changed since a base ref. Any non-zero git exit is wrapped as FILTER_CHANGED with git's stderr appended, so the underlying git failure (usually a bad or missing revision) is visible.","triggerScenarios":"Using `--filter ...@<since>` (or otherwise triggering changed-files filtering) with a `<since>` that git cannot resolve: typo'd ref, a base commit absent from a shallow clone, running outside a git repository, or a corrupted .git.","commonSituations":"CI shallow clones (fetch-depth too small) where the base commit was never fetched; typo'd since value like 'mainn'; pipelines running on exported tarballs without .git.","solutions":["Confirm the ref resolves locally: `git cat-file -t <since>`; fix typos / use origin/main.","Deepen or unshallow the clone so the base commit exists: `git fetch --unshallow` or increase fetch-depth.","Run the command inside the repository working tree (not an exported copy)."],"exampleFix":"# before: shallow clone missing the base ref\n$ pnpm --filter='...@origin/main^' build   # ERR_PNPM_FILTER_CHANGED: bad revision\n\n# after\n$ git fetch --unshallow origin main   # or: git fetch --depth=500 origin main\n$ pnpm --filter='...@origin/main^' build","handlingStrategy":"validation","validationCode":"import { execSync } from 'node:child_process'\n\nfunction refExists (since: string, cwd: string): boolean {\n  try {\n    execSync(`git cat-file -e ${JSON.stringify(since)}^{commit}`, { cwd, stdio: 'ignore' })\n    return true\n  } catch {\n    return false\n  }\n}\nif (!refExists(since, repoDir)) {\n  await fetchDeeply(repoDir) // e.g. git fetch --unshallow\n}","typeGuard":null,"tryCatchPattern":"try {\n  await runFiltered({ since })\n} catch (err) {\n  if ((err as NodeJS.ErrnoException).code === 'ERR_PNPM_FILTER_CHANGED' && /bad revision|unknown revision/.test(String(err.message))) {\n    await gitFetchDeeply() // fix the clone, then retry once\n    return runFiltered({ since })\n  }\n  throw err\n}","preventionTips":["Fetch full or sufficiently deep history in CI before using @since filters.","Validate the `<since>` ref resolves (`git cat-file -t`) before invoking filtered commands.","Always run pnpm inside the git working tree, never on an exported archive."],"tags":["git","filtering","workspace","ci"],"backgroundTag":"invalid-git-ref","analyzedSha":"6261b7f388016d57ca6b90340342411cd1d0d00f","analyzedAt":"2026-08-17T18:30:54.750Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}