Files
llm-wiki/raw/errors/gradle-strict-lock-stale-entry-non-resolvable-config-2026-07-08.md
T

5.1 KiB

title, source_type, status, related_branches, related_projects, tags, created, status_label
title source_type status related_branches related_projects tags created status_label
error / gradle-strict-lock-stale-entry-non-resolvable-config-2026-07-08 error-note raw
chore-ulid-to-uuidv7
ca-skeleton
error
ca-skeleton
gradle
dependency-locking
strict-lock
resolveAndLockAll
sampleFixture
2026-07-08 resolved

error: gradle-strict-lock-stale-entry-non-resolvable-config-2026-07-08

Layer: raw/errors/ — 작업 중 마주친 단일 실패·트러블슈팅 기록. 원본은 raw에 영구 보관한다.

Parent / 부모

증상 / Symptom

  • com.github.f4b6a3:ulid-creator:5.2.3uuid-creator:6.1.1 로 build.gradle 2곳을 바꾸고 cd src && ./gradlew resolveAndLockAll --write-locks (BUILD SUCCESSFUL) 실행 후에도, app-bootstrap/gradle.lockfile낡은 줄이 남음:
    com.github.f4b6a3:ulid-creator:5.2.3=sampleFixture
    com.github.f4b6a3:uuid-creator:6.1.1=productionRuntimeClasspath,runtimeClasspath,sampleOffTestRuntimeClasspath,testRuntimeClasspath
    
    uuid-creator 는 resolvable config 들에 잡혔지만 sampleFixture config 태그는 여전히 ulid-creator 를 가리킴.
  • 발생 컨텍스트: 의존 교체 후 STRICT lock 재생성. 발생 시점: 2026-07-08. 재현 가능 여부: always — non-resolvable config 를 통과하는 의존이 버전 변경될 때마다.

재현 절차 / Reproduction

  1. app-bootstrap/build.gradle 처럼 configurations { sampleFixture { canBeConsumed=false; canBeResolved=false } } 를 두고 testCompileClasspath.extendsFrom sampleFixture 로 확장.
  2. sampleFixture project(':sample-portfolio') 가 끌어오는 전이 의존의 버전을 바꿈(여기선 sample-portfolio 의 ulid-creatoruuid-creator).
  3. cd src && ./gradlew resolveAndLockAll --write-locks 실행.
  4. 기대: 모든 lock 태그가 새 좌표로 갱신. 실제: =sampleFixture 로만 태그된 낡은 좌표가 lockfile 에 잔존.

근본 원인 / Root cause

  • 직접 원인: resolveAndLockAll 태스크 본문이 configurations.findAll { it.canBeResolved }.each { it.resolve() }canBeResolved = falsesampleFixture 는 필터에서 제외되어 직접 resolve 되지 않음. --write-locks 는 그 실행에서 resolve 된 config 의 lock 항목만 다시 씀. resolve 안 된 config 의 기존 항목은 삭제/갱신되지 않고 보존된다.
  • 근본 원인: STRICT lock 이 실패하지 않는 이유 — sampleFixture 는 어떤 빌드에서도 직접 resolve 되지 않으므로 그 태그의 lock 항목은 검증되지 않는다(확장 대상인 testRuntimeClasspath 등은 새 uuid-creator 로 올바르게 검증됨). 그래서 조용히 통과하지만, 커밋되는 lockfile 에 사라진 의존(ulid-creator)이 남아 "ULID 완전 제거" 계약을 위반.

해결 / Resolution

  • 적용한 조치: lockfile 수동 병합 — 낡은 ulid-creator:5.2.3=sampleFixture 줄을 삭제하고, uuid-creator:6.1.1 줄의 config 목록에 sampleFixture알파벳 위치(runtimeClasspath 다음, sampleOffTestRuntimeClasspath 앞)에 삽입:
    com.github.f4b6a3:uuid-creator:6.1.1=productionRuntimeClasspath,runtimeClasspath,sampleFixture,sampleOffTestRuntimeClasspath,testRuntimeClasspath
    
    (sample-portfolio→uuid-creator 이므로 sampleFixture 가 uuid-creator 를 포함하는 것이 올바른 상태. resolvable config 목록은 건드리지 않아 누락 위험 없음.)
  • 검증 방법: cd src && ./gradlew check (내부에서 verifyDependencyLocks STRICT 재해석) BUILD SUCCESSFUL — lockfile 일관성 확인. 전 lockfile grep 으로 ulid-creator 0건 확인.
  • 잔여 위험 / 후속: 대안 = sampleFixture { canBeResolved = true } 로 일시 전환 후 resolveAndLockAll 재실행하고 원복. 수동 편집보다 재현성은 높으나 build.gradle 변경 위험이 있어 이번엔 타깃 lock 편집을 택함.

회고 / Lessons

  • 빨리 감지하는 신호: 전이 의존 버전을 바꾼 뒤 모든 *.lockfile 에서 OLD 좌표를 grep 한다 — resolveAndLockAll 성공 로그만 믿지 않는다.
  • 예방 체크리스트: canBeResolved=false 인 aggregation/bucket config(예: sampleFixture)는 resolveAndLockAllfindAll { it.canBeResolved } 필터에서 빠진다 → 그 태그의 lock 항목은 자동 갱신 안 됨. 버킷을 확장하는 resolvable config 는 갱신되지만 버킷 태그 자체는 stale 로 남는다.
  • 일반화된 교훈: Gradle STRICT locking 에서 "빌드가 통과한다 ≠ lockfile 이 깨끗하다". non-resolvable config 의 lock 항목은 검증 사각지대라, 의존 삭제/교체 시 수동 대조가 필요하다.