Repository navigation
[bug] teamai packages install crashes in pnpm projects (npm install run in pnpm node_modules tree) #1102
Description
Description
teamai packages install (local / non‑global declarations) always fails in a project that uses pnpm, because the npm adapter shells out to npm install with cwd set to the project root. npm's arborist then tries to read the project's pnpm node_modules layout and crashes:
npm error Cannot read properties of null (reading 'matches')
Root cause chain (npm 11.16.0):
TypeError: Cannot read properties of null (reading 'matches')
at Link.matches (…/npm/node_modules/@npmcli/arborist/lib/node.js:1183:41)
at Link.canDedupe (…/lib/node.js:1127:15)
at PlaceDep.pruneDedupable (…/lib/place-dep.js:426:14)
at new PlaceDep (…/lib/place-dep.js:278:14)
npm install cannot understand node_modules/.pnpm/** (the symlink farm pnpm creates), so arborist walks a Link whose target is null and dereferences it.
Two problems for a pnpm project:
- teamai never detects the package manager.
grep -c pnpmoverteamai-cli@0.27.0/dist/index.js→ 0. The npm adapter hardcodes:There is nothis.execute("npm", ["install", …(global ? ["--global"] : []), …specs, …(registry ? ["--registry", registry] : [])], { cwd: context.cwd })
packageManagerfield read, no pnpm/yarn/bun detection, no override knob. - Local installs run npm inside the project directory, i.e. exactly the pnpm tree that breaks arborist. (Global installs —
--global— do not crash, since they don't parse the project'snode_modules.)
Expected: in a pnpm project, teamai packages install should install through pnpm (pnpm add / pnpm add -g), or at minimum not crash and print an actionable message. Issue #325 ("TeamAI 不重造任何包管理器") reserved architecture slots for other ecosystems; pnpm is a package-manager flavor of the npm ecosystem and is currently unsupported.
Reproduction
Minimal, no teamai config needed — the crash is reproducible with a bare npm command in any pnpm project:
# 1. pnpm project with an installed pnpm store
pnpm install
# 2. npm install in that same directory → crash (even --dry-run)
npm install --dry-run lodash
# npm error Cannot read properties of null (reading 'matches')Then through teamai (project scope, packages.npm declared or a fresh target):
teamai packages install typescript
# npm error Cannot read properties of null (reading 'matches')
# Error: npm install failed (exit 1): npm error Cannot read properties of null …
# at NpmAdapter.install (…/teamai-cli/dist/index.js:36059:19)
# at async pkgInstall (…/dist/index.js:36516:7)Control test proving it is the pnpm layout, not the network or the package:
mkdir /tmp/npmtest && cp package.json /tmp/npmtest/ && cd /tmp/npmtest
npm install --dry-run lodash # succeeds — no node_modules/.pnpm here
rm -rf /tmp/npmtestGlobal path also proves the split:
teamai packages install @playwright/cli --global # works (no project node_modules walked)Expected vs actual
- Expected:
teamai packages install <pkg>in a pnpm project resolves the dependency graph with pnpm (respectingpnpm-lock.yaml), or exits cleanly with a "pnpm not supported" message. - Actual: an opaque arborist
TypeErrorsurfaced asnpm install failed (exit 1), with no hint that the real cause is npm-vs-pnpm layout.
Environment
- OS: Ubuntu 26.04.1 LTS (x64)
- Node.js:
v24.18.0 - npm:
11.16.0 - pnpm:
12.10.1 - teamai:
0.27.0 - Provider: CNB (cnb.cool)
- AI tool(s): CodeBuddy
Suggested fixes (any of)
- Detect the package manager. Read
package.json#packageManager/ presence ofpnpm-lock.yaml/pnpm-workspace.yaml, and route topnpm add [-g]/yarn add/bun addaccordingly. (This is the "扩展位" the Proposal: teamai install — 统一编排 npm 依赖与 Claude 插件市场 #325 design reserved.) - Add an explicit override (config key or flag) so a member can force the package manager for a project.
- Guard the npm path. When a foreign layout is detected (e.g.
node_modules/.pnpmexists and the project declares pnpm), skip the npm adapter and warn rather than throw an opaque arborist crash. - Nice-to-have: wrap the
npm installfailure so the error names the likely cause when a pnpm/yarn layout is present.
Logs
`teamai packages install typescript` (verbose)
npm error Cannot read properties of null (reading 'matches')
npm error A complete log of this run can be found in: /home/bladestone/.npm/_logs/2026-10-13T14_24_16_515Z-debug-0.log
file:///…/teamai-cli/dist/index.js:36059
throw new Error(`npm install failed (exit ${result.code}): ${result.stderr.trim()}`);
^
Error: npm install failed (exit 1): npm error Cannot read properties of null (reading 'matches')
at NpmAdapter.install (file:///…/teamai-cli/dist/index.js:36059:19)
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
at async pkgInstall (file:///…/teamai-cli/dist/index.js:36516:7)
at async run2 (file:///…/teamai-cli/dist/index.js:67881:3)
Node.js v24.18.0
npm debug log excerpt:
189 verbose stack TypeError: Cannot read properties of null (reading 'matches')
189 verbose stack at Link.matches (…/@npmcli/arborist/lib/node.js:1183:41)
189 verbose stack at Link.canDedupe (…/node.js:1127:15)
189 verbose stack at PlaceDep.pruneDedupable (…/place-dep.js:426:14)
189 verbose stack at new PlaceDep (…/place-dep.js:278:14)
189 verbose stack at async Arborist.buildIdealTree (…/build-ideal-tree.js:995:18)
195 verbose cwd /path/to/pnpm-project
198 verbose npm v11.16.0
Activity
akushonkamen commentedon Oct 14, 2026
I'd like to take this one.
Root cause confirmed:
NpmAdapter.install()unconditionally shells out tonpm installwithcwdset to the project root (src/pkg/adapters/npm.ts, thethis.execute('npm', args, { cwd: context.cwd, ... })call, ~L155). There is no package-manager detection (pnpm-workspace.yaml/packageManagerfield), andsnapshotLocal()(~L74) only readspackage-lock.json. I reproduced the arborist crash (Cannot read properties of null (reading 'matches'), exit 1) by runningnpm install --dry-runin a pnpm workspace with a transitive dependency tree — on both npm 11.9.0 and npm 11.16.0.Planned fix: detect a pnpm project (
pnpm-workspace.yaml,pnpm-lock.yaml, orpackage.json#packageManagerstarting withpnpm) and route installs throughpnpm add [-g](snapshot viapnpm list --json), keeping the npm path byte-for-byte unchanged for non-pnpm projects.akushonkamen commentedon Oct 14, 2026
PR opened: #1116 — detects pnpm (
pnpm-workspace.yaml/pnpm-lock.yaml/packageManagerfield) and routes installs throughpnpm add, with snapshots frompnpm list --json. npm path unchanged; red-to-green repro and test evidence in the PR description.fix(packages): honor an explicit npm pin over a pnpm ancestor (Tencen…