TechFeedTechFeed
Programming Languages

outdated lockfile, pnpm-lock, 얼린 설치 | 액션만 락파일을 거절하면?

ERR_PNPM_OUTDATED_LOCKFILE는 package.json만 바뀌고 락을 커밋하지 않으면 연속 통합의 얼린 설치가 거절하는 코드입니다. 로컬에서 설치로 락을 갱신해 올리고, 피어 충돌과 해시 실패는 다른 줄로 가릅니다. pnpm, 깃허브 액션, 워크스페이스, 한국 1인 개발. 2026년 9월 pnpm 문서.

by

ERR_PNPM_OUTDATED_LOCKFILE는 패키지가 없어서가 아니라, package.json만 바뀌고 pnpm-lock.yaml은 그대로인 채 얼린 설치가 돌아서 납니다. 로컬은 락을 고치고, 연속 통합 환경은 그 수정을 거절합니다.


의존성만 올리고 락을 빼먹은 커밋은 액션에서만 빨간 줄이 됩니다. 피어가 안 맞아 트리를 못 짜는 실패와는 자리가 다릅니다. 워크스페이스라면 루트에서 돌려야 하위 패키지까지 락이 맞습니다.


루트에서 pnpm install을 돌리고 락 차이를 커밋하면 다음 잡은 지나갑니다. 근거는 pnpm 오류 코드와 설치 문서입니다.


락이 낡으면 왜 설치가 멈추나

락과 매니페스트가 어긋나면 얼린 설치는 실패합니다. pnpm 오류 문서는 이 코드를, 락파일을 고치지 않고는 설치를 끝낼 수 없을 때 난다고 적습니다. 흔한 경로는 두 가지입니다. package.json만 고치고 pnpm install을 안 돌렸거나, 돌렸는데 락 변경을 커밋하지 않았습니다.


로컬에서는 기본값이 다릅니다. 문서의 frozen-lockfile은 CI가 아니면 기본 false라, 일반 pnpm install은 락을 새로 쓰고 설치를 마칩니다. 그래서 내 노트북은 초록인데 원격 잡만 거절하는 그림이 나옵니다.


preferFrozenLockfile 기본값은 true입니다. 락이 package.json의 범위를 이미 만족하면 해석을 건너뛰는 헤드리스 설치를 합니다. 범위를 만족하지 못하면 그 지름길을 못 타고, CI에서는 갱신 대신 실패로 떨어집니다.


먼저 볼 줄 | 로그에 ERR_PNPM_OUTDATED_LOCKFILE가 있으면 캐시부터 지우지 마세요. 지울 대상은 node_modules가 아니라, 커밋되지 않은 pnpm-lock.yaml 쪽입니다.


패키지 설치가 멈춘 뒤 확인할 서버 장비와 케이블이 있는 작업 공간
로컬 설치는 락을 고치고, CI의 얼린 설치는 그 수정을 거절한다

액션에서만 거절되는 이유

CI로 감지되면 frozen-lockfile이 기본으로 켜집니다. pnpm install 문서는 CI 환경 변수가 있거나 젠킨스의 BUILD_NUMBER, 일부 러너의 RUN_ID처럼 ci-info가 CI로 보는 값이면 얼린 설치로 본다고 적습니다. 깃허브 액션은 CI=true를 넣으므로 이 분기에 들어갑니다.


얼린 설치는 락을 생성하지 않습니다. 락이 매니페스트와 어긋나거나, 락이 없거나, 갱신이 필요하면 설치가 실패합니다. 같은 저장소를 노트북에서 pnpm install 하면 락이 고쳐지니, "내 자리에선 되는데"가 그대로 설명됩니다.


pnpm 11부터는 CI에서 락을 쓴 메이저와 러너의 pnpm 메이저가 안 맞으면 조용히 다시 쓰지 않고 실패하기도 합니다. 그 경우는 의존성 한 줄보다 액션이 쓰는 pnpm 버전을 먼저 맞춥니다. packageManager 필드나 액션의 버전 인자를 락을 만든 버전과 같게 두면 됩니다.


자리기본 동작락이 낡으면
노트북frozen-lockfile 기본 꺼짐락을 고치고 설치를 마침
깃허브 액션CI라 얼린 설치OUTDATED_LOCKFILE로 거절
pnpm ci항상 얼린 설치로컬이라도 같은 거절
메이저가 다름11부터 CI는 재작성 안 함러너 pnpm 버전을 맞춤

로컬에서 락만 갱신하고 커밋하기
# 저장소 루트. CI=true 가 있으면 잠시 끄고 돌린다 cd /path/to/repo pnpm install git diff -- pnpm-lock.yaml package.json git add pnpm-lock.yaml package.json # 다음 액션은 얼린 설치로 같은 락을 쓴다

락을 다시 쓰고 올리는 순서

고치는 곳은 러너가 아니라 락을 만든 커밋입니다. 패키지를 추가한 브랜치에서 pnpm install을 실행하고, pnpm-lock.yaml이 바뀌었는지 git diff로 확인한 다음 그 파일을 같은 커밋에 넣습니다. 의존성만 올리고 락을 빼먹으면 액션이 다시 같은 코드를 냅니다.


락만 고치고 디스크의 node_modules는 나중에 받아도 되면 pnpm install --lockfile-only가 있습니다. 문서상 이 플래그는 pnpm-lock.yaml만 갱신합니다. 올린 뒤에는 액션이 얼린 설치로 그 락을 받아 node_modules를 채웁니다.


워크스페이스는 루트에서 한 번이 안전합니다. 하위 폴더에서만 설치하면 그 패키지의 importer 블록만 움직이고, 다른 패키지 락과 어긋난 채 푸시될 수 있습니다. pnpm-workspace.yaml에 패키지를 넣거나 뺐다면 루트 락이 그 목록과 맞아야 합니다.


액션에서 얼린 설치를 그대로 쓰기
# 락이 이미 커밋된 뒤의 CI pnpm install --frozen-lockfile # 또는 pnpm 11+ pnpm ci
락파일 갱신 순서를 확인할 때 보는 장비와 케이블
diff에 pnpm-lock.yaml이 보이면 그 파일을 의존성 커밋에 함께 넣는다

피어 충돌, 해시 실패와 가르기

코드 이름이 비슷해도 고치는 파일이 다릅니다. ERR_PNPM_PEER_DEP_ISSUES는 피어 범위가 안 맞을 때고, ERR_PNPM_TARBALL_INTEGRITY는 받은 압축 파일의 해시가 락의 기대값과 다를 때입니다. OUTDATED_LOCKFILE는 그 전에, 락을 갱신해야 설치가 진행된다는 뜻입니다.


npm의 ERESOLVE도 다른 칸입니다. 그건 피어 버전을 한 트리로 못 맞출 때 설치가 멈추는 쪽이라, 락을 커밋한다고 풀리지 않을 수 있습니다. 피어 의존성 충돌은 Found 줄과 요구 버전을 읽고, 이 글의 코드는 git status에 락이 없는지를 먼저 봅니다.


해시가 틀리면 캐시나 락의 integrity 줄을 봅니다. 그 자리는 EINTEGRITY 체크섬 글과 pnpm 문서의 TARBALL_INTEGRITY입니다. 모듈 이름을 못 찾는 줄은 설치가 끝난 뒤의 실행 문제라 Cannot find module과 순서가 다릅니다.


코드의미먼저 할 일
OUTDATED_LOCKFILE락을 고쳐야 설치가 됨로컬 install 후 락 커밋
PEER_DEP_ISSUES피어 범위가 안 맞음빠진 피어를 설치
TARBALL_INTEGRITY받은 파일 해시가 다름락 머지 또는 스토어
FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE고정한 pnpm 버전이 락과 다름버전 핀을 다시 기록

마지막 줄은 pnpm 11.23 이후 문서에 있습니다. packageManager나 devEngines로 고정한 pnpm 버전이 락의 기록과 다르면 얼린 설치가 ERR_PNPM_FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE로 실패합니다. 의존성 줄은 그대로인데 핀만 올렸다면, 얼림 없이 install 해서 락의 버전 기록을 갱신한 뒤 커밋합니다.


패키지 하나만 바꾼 워크스페이스

앱 폴더의 package.json만 고치고 루트 락을 안 건드리면 액션이 거절합니다. pnpm은 워크스페이스에서 루트 install이 모든 프로젝트 의존성을 설치한다고 문서에 적습니다. 필터를 써도 락 파일은 루트 pnpm-lock.yaml 하나입니다.


모노레포에서 자주 빠지는 파일은 락입니다. 프리티어나 린트가 package.json만 보여주고 pnpm-lock.yaml은 생성 파일이라고 무시하면, 리뷰에서 락 diff가 사라집니다. 무시 목록에 락이 들어가 있는지 한 번 보세요. 락은 커밋하는 파일입니다.


다른 브랜치가 같은 락을 먼저 머지했다면, 내 락을 통째로 덮어쓰지 말고 최신 메인을 받은 뒤 루트에서 pnpm install을 다시 돌립니다. 그러면 importer 블록이 양쪽 변경을 한 파일에 다시 씁니다. 충돌 마커를 락 안에 남기면 다음 오류는 파싱 실패나 해시 불일치로 바뀝니다.


한국에서 혼자 넥스트 앱과 스크립트 패키지를 한 저장소에 두는 경우에도 같습니다. 프리뷰 잡이 pnpm install로 실패하면, 버셀 대시보드의 설치 명령을 바꾸기 전에 그 커밋에 락이 들어갔는지 확인하면 됩니다. 설치 명령이 npm ci인데 저장소는 pnpm이면 락 이름이 달라 또 다른 실패가 납니다. 패키지 매니저는 하나와 그 락만 액션에 맞춥니다.


원격 잡의 로그는 길어도 맨 위 코드만 보면 손이 가는 파일이 정해집니다. 락이 낡았다는 코드라면 스토어를 비우거나 의존성 버전을 무작정 내리지 않아도 됩니다. 커밋 목록에 매니페스트만 있고 락이 없으면 그 커밋을 고칩니다. 여러 패키지를 한 저장소에 둔 경우에도 락은 루트에 하나이므로, 앱 폴더만 열고 설치한 뒤 푸시하면 같은 거절이 납니다.


리뷰에서 락 차이가 길다는 이유로 그 파일을 빼면, 다음 사람의 컴퓨터는 조용히 락을 다시 쓰고 원격만 계속 실패합니다. 설치 단계에서 프리뷰가 멈추면 빌드 이미지보다 그 커밋에 락이 들어갔는지를 먼저 엽니다. 도구를 두 개로 섞으면 락 이름이 달라 다른 실패가 나므로, 저장소가 고른 도구 하나로 액션 명령을 맞춥니다. 락을 생성물로 보고 커밋에서 빼지 않겠다는 약속을 리뷰 전에 적어 두면, 매주 같은 빨간 잡이 반복되지 않습니다.


참고 자료


내부 연계: npm 피어 충돌, EINTEGRITY 체크섬, 모듈을 못 찾는 줄, exports가 닫힌 하위 경로


인용한 기본값은 2026년 9월 pnpm 12 문서 기준입니다.


자주 묻는 질문

node_modules를 지우면 이 오류가 사라지나요?

아니요. 얼린 설치는 디스크 폴더가 아니라 락과 package.json의 차이를 보고 멈춥니다. 폴더를 지운 뒤에도 CI는 같은 락으로 다시 거절합니다. 로컬에서 install 해 락을 갱신하고 그 파일을 커밋해야 합니다.


액션에 --no-frozen-lockfile을 넣으면 되나요?

그때의 잡은 넘어갈 수 있지만, 러너가 고친 락은 저장소에 남지 않습니다. 다음 커밋에서 다시 어긋납니다. 락을 고치는 곳은 개발 브랜치이고, 액션은 그 락을 읽기만 하는 쪽이 맞습니다.


로컬에서도 pnpm ci가 같은 코드로 실패합니다.

pnpm ci는 문서상 클린 뒤 frozen-lockfile 설치입니다. CI 변수가 없어도 얼린 설치라, 락이 낡으면 노트북에서도 거절합니다. 갱신은 pnpm install로 하고, ci는 락을 커밋한 다음에 돌리면 됩니다.


package.json은 안 바꿨는데도 실패합니다.

워크스페이스 목록, pnpm 버전 핀, 중첩된 package.json 중 하나가 락과 다를 수 있습니다. 11.23 이후에는 고정한 pnpm 버전만 달라도 FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE가 납니다. 오류 코드 전체를 읽고, 핀이면 얼림 없이 install 해 락의 버전 기록을 맞춥니다.


npm ci와 같이 써도 되나요?

한 저장소에서 매니저는 하나로 두는 편이 낫습니다. pnpm-lock.yaml만 있고 package-lock.json이 없으면 npm ci는 그 락을 읽지 못합니다. 액션의 설치 명령을 저장소가 커밋한 락과 같은 도구로 맞추세요.


해시 오류와 어떻게 구분하나요?

OUTDATED_LOCKFILE는 설치가 락을 고쳐야 한다는 뜻입니다. TARBALL_INTEGRITY나 npm EINTEGRITY는 받은 파일의 해시가 락에 적힌 값과 다르다는 뜻입니다. 앞의 것은 락을 커밋하고, 뒤의 것은 머지 충돌이나 캐시를 봅니다.


이 코드는 package.json과 pnpm-lock.yaml을 같은 커밋에 두었는가에서 갈립니다. 노트북에서 pnpm install로 락을 갱신해 올리고, 액션은 얼린 설치로 그 파일을 읽게 두면 다음 잡은 같은 줄에서 지나갑니다. 관련 글: 피어 충돌, 체크섬 불일치, exports 하위 경로.


ERR_PNPM_OUTDATED_LOCKFILEpnpm락파일frozen-lockfileCI워크스페이스패키지설치개발자

함께 보면 좋은 문제 해결

EXPLORE / Programming Languages

이어서 읽어보기

전체 토픽 둘러보기 →