Status Update
Comments
sp...@google.com <sp...@google.com> #2
I think the problem is this line in LintTool.initializeLintCacheDir()
:
val previousVersion = lintVersionMarkerFile.takeIf { Files.exists(it) }?.let { Files.readAllLines(it).singleOrNull() }
Maybe it would be sufficient to add @Synchronized
to LintTool.initializeLintCacheDir()
ga...@google.com <ga...@google.com>
sp...@google.com <sp...@google.com>
sp...@google.com <sp...@google.com> #3
Have you seen this again since that first time, Aurimas?
sp...@google.com <sp...@google.com> #5
Closing this since it did not happen again, but please reopen if it does
mi...@allegro.com <mi...@allegro.com> #6
Hey, we're experiencing this (or at least very similar) issue on a regular basis in our project. Our setup:
Gradle 8.5
Gradle Enterprise plugin 3.15.1
Android Gradle plugin 8.2.2
android-cache-fix-gradle-plugin 3.0.1
Kotlin 1.9.22
JDK 17 Temurin
With build cache server:
boolean isCi = System.getenv('GITHUB_ACTIONS')
buildCache {
remote(HttpBuildCache) {
url = 'https://gradlecache.our-server.com/cache/'
push = isCi
}
}
Intermediate lint result contains the following errors:
/home/github/actions-runner/_work/our_app/some_module/some_file.kt: Error: Unexpected failure during lint analysis of some_file.kt (this is a bug in lint or one of the libraries it depends on)
Message: java.nio.file.NoSuchFileException: /home/github/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.9.22/d6c44cd08d8f3f9bece8101216dbe6553365c6e3/kotlin-stdlib-1.9.22.jar
The crash seems to involve the detector com.android.tools.lint.checks.ExifInterfaceDetector.
You can try disabling it with something like this:
android {
lint {
disable "ExifInterface"
}
}
Stack: RuntimeException:CoreStubTreeLoader.build(CoreStubTreeLoader.java:44)←CoreStubTreeLoader.readOrBuild(CoreStubTreeLoader.java:29)←ClsFileImpl.getStubTree(ClsFileImpl.java:483)←ClsFileImpl.getStub(ClsFileImpl.java:452)←ClsFileImpl.getClasses(ClsFileImpl.java:135)←KotlinCliJavaFileManagerImpl$Companion.findClassInPsiFile(KotlinCliJavaFileManagerImpl.kt:291)←KotlinCliJavaFileManagerImpl$Companion.access$findClassInPsiFile(KotlinCliJavaFileManagerImpl.kt:287)←KotlinCliJavaFileManagerImpl.findPsiClassInVirtualFile(KotlinCliJavaFileManagerImpl.kt:257)←KotlinCliJavaFileManagerImpl.access$findPsiClassInVirtualFile(KotlinCliJavaFileManagerImpl.kt:49)←KotlinCliJavaFileManagerImpl$findPsiClass$1.invoke(KotlinCliJavaFileManagerImpl.kt:71)←KotlinCliJavaFileManagerImpl$findPsiClass$1.invoke(KotlinCliJavaFileManagerImpl.kt:49)←PerformanceCounter.time(PerformanceCounter.kt:90)←KotlinCliJavaFileManagerImpl.findPsiClass(KotlinCliJavaFileManagerImpl.kt:70)←KotlinCliJavaFileManagerImpl.findClass(KotlinCliJavaFileManagerImpl.kt:154)←PsiElementFinderImpl.findClass(PsiElementFinderImpl.java:40)←JavaPsiFacadeImpl.doFindClass(JavaPsiFacadeImpl.java:94)←JavaPsiFacadeImpl.findClass(JavaPsiFacadeImpl.java:72)←ClsJavaCodeReferenceElementImpl.resolveElement(ClsJavaCodeReferenceElementImpl.java:255)←ClsJavaCodeReferenceElementImpl.advancedResolveImpl(ClsJavaCodeReferenceElementImpl.java:152)←ClsJavaCodeReferenceElementImpl.access$000(ClsJavaCodeReferenceElementImpl.java:42)←ClsJavaCodeReferenceElementImpl$Resolver.resolve(ClsJavaCodeReferenceElementImpl.java:145)←ClsJavaCodeReferenceElementImpl$Resolver.resolve(ClsJavaCodeReferenceElementImpl.java:140)←ResolveCache.lambda$resolveWithCaching$2(ResolveCache.java:176)←Computable.get(Computable.java:16)←ResolveCache.lambda$loggingResolver$4(ResolveCache.java:237)←RecursionManager$1.computePreventingRecursion(RecursionManager.java:112)←RecursionGuard.doPreventingRecursion(RecursionGuard.java:42)←RecursionManager.doPreventingRecursion(RecursionManager.java:66)←ResolveCache.resolve(ResolveCache.java:214)←ResolveCache.resolveWithCaching(ResolveCache.java:176)←ClsJavaCodeReferenceElementImpl.multiResolve(ClsJavaCodeReferenceElementImpl.java:215)←ClsJavaCodeReferenceElementImpl.advancedResolve(ClsJavaCodeReferenceElementImpl.java:203)←PsiClassReferenceType.resolveGenerics(PsiClassReferenceType.java:183)←PsiClassReferenceType.resolve(PsiClassReferenceType.java:122)←PsiTypesUtil.getPsiClass(PsiTypesUtil.java:146)←KotlinInternalUastUtilsKt.resolveToPsiClass(kotlinInternalUastUtils.kt:518)←KotlinInternalUastUtilsKt.resolveToDeclarationImpl(kotlinInternalUastUtils.kt:439)←KotlinInternalUastUtilsKt.resolveToDeclarationImpl(kotlinInternalUastUtils.kt:413)←KotlinUastResolveProviderService.resolveToDeclaration(KotlinUastResolveProviderService.kt:321)←KotlinUImportStatement$ImportReference.resolve(KotlinUImportStatement.kt:52)←KotlinUImportStatement.resolve(KotlinUImportStatement.kt:36)←ExifInterfaceDetector$MyVisitor.visitImportStatement(ExifInterfaceDetector.java:164)←UElementVisitor$DispatchPsiVisitor.visitImportStatement(UElementVisitor.kt:691)←UElementVisitor$DelegatingPsiVisitor.visitImportStatement(UElementVisitor.kt:973)←UImportStatement.accept(UImportStatement.kt:41)←ImplementationUtilsKt.acceptList(implementationUtils.kt:15)←UFile.accept(UFile.kt:88)←UastLintUtilsKt.acceptSourceFile(UastLintUtils.kt:826)←UElementVisitor$visitFile$3.run(UElementVisitor.kt:267)←LintClient.runReadAction(LintClient.kt:1705)←LintDriver$LintClientWrapper.runReadAction(LintDriver.kt:2903)←UElementVisitor.visitFile(UElementVisitor.kt:264)←LintDriver$visitUastDetectors$1.run(LintDriver.kt:2179)←LintClient.runReadAction(LintClient.kt:1705)←LintDriver$LintClientWrapper.runReadAction(LintDriver.kt:2903)←LintDriver.visitUastDetectors(LintDriver.kt:2179)←LintDriver.visitUast(LintDriver.kt:2141)←LintDriver.runFileDetectors(LintDriver.kt:1387)←LintDriver.checkProject(LintDriver.kt:1152)←LintDriver.checkProjectRoot(LintDriver.kt:623)←LintDriver.access$checkProjectRoot(LintDriver.kt:172)←LintDriver$analyzeOnly$1.invoke(LintDriver.kt:446)←LintDriver$analyzeOnly$1.invoke(LintDriver.kt:443)←LintDriver.doAnalyze(LintDriver.kt:502)←LintDriver.analyzeOnly(LintDriver.kt:443)←LintCliClient$analyzeOnly$1.invoke(LintCliClient.kt:233)←LintCliClient$analyzeOnly$1.invoke(LintCliClient.kt:233)←LintCliClient.run(LintCliClient.kt:275)←LintCliClient.run$default(LintCliClient.kt:258)←LintCliClient.analyzeOnly(LintCliClient.kt:233)←Main.run(Main.java:1761)←Main.run(Main.java:284)←GeneratedMethodAccessor1391.invoke(null:-1)←DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)←Method.invoke(Method.java:568)←AndroidLintWorkAction.invokeLintMainRunMethod(AndroidLintWorkAction.kt:98)←AndroidLintWorkAction.runLint(AndroidLintWorkAction.kt:87)←AndroidLintWorkAction.execute(AndroidLintWorkAction.kt:62)←DefaultWorkerServer.execute(DefaultWorkerServer.java:63)←NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)←NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)←ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)←NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)←AbstractWorker$1.call(AbstractWorker.java:44)←AbstractWorker$1.call(AbstractWorker.java:41)←DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)←DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)←DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)←DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)←DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)←DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)←DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)←DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)←AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)←NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)←DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:170)←FutureTask.run(FutureTask.java:264)←DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:187)←DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:120)←DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:162)
The only way to solve the issue is to clean cache on our remote cache server. I wasn't able to reproduce the issue, but it occurs at least once a month in our current setup. It's also worth mentioning that no other Gradle task on our CI is suffering from cache related issues (assemble, unitTest etc.) - only Lint is affected.
Any ideas?
sp...@google.com <sp...@google.com> #7
Is the missing file always kotlin-stdlib-1.9.22.jar ?
Do you have any other information you can share to help me reproduce the issue?
mi...@allegro.com <mi...@allegro.com> #8
No, it's not always kotlin-stdlib. I've attached the full report with redacted file paths and module names. Please note it reports some resources as unused at the end which is not true and probably caused by the premature failure.
Additional info:
- Lint configuration
lint {
abortOnError = true
warningsAsErrors = true
checkDependencies = true
ignoreTestSources = true
baseline = File("lint-baseline.xml")
}
We also use some custom Lint rules which are applied via dependencies block lintChecks project(':lint-checks')
We have a large baseline file with the following format:
<issues format="6" by="lint 8.2.2" type="baseline" client="gradle" dependencies="true" name="AGP (8.2.2)" variant="all" version="8.2.2">
- Cache - our .gradle/caches are shared between builds via Github Action
gradle/actions/setup-gradle@v3
- name: Setup Gradle Cache
uses: gradle/actions/setup-gradle@v3
with:
gradle-home-cache-cleanup: true
gradle-home-cache-excludes: caches/build-cache-1
We exclude build-cache as it is provided by our remote cache server. Removing .gradle/caches
does not influence this issue - lint still fails with attached logs.
- Github Actions - we use Ubuntu 22.04 runners
ma...@allegro.com <ma...@allegro.com> #9
After a quick investigation, we suspect that the root cause of those fails is the build/intermediates/lint_model/debug/debug_artifact_libraries.xml
file. When looking at it's content in an example module:
<libraries>
<library
name="androidx.annotation:annotation-jvm:1.6.0@jar"
jars="/Users/name.surname/.gradle/caches/modules-2/files-2.1/androidx.annotation/annotation-jvm/1.6.0/a7257339a052df0f91433cf9651231bbb802b502/annotation-jvm-1.6.0.jar"
resolved="androidx.annotation:annotation-jvm:1.6.0"
provided="true"/>
....
</libraries>
That's right, this file has a reference to a Gradle cache directory. I'm not a Gradle expert, but I assume that this is something that has potential to break the cache logic.
ma...@allegro.com <ma...@allegro.com> #10
This issue was discovered when using Gradle 8.5 and AGP 8.2.2, but I've tested it on Gradle 8.7 and AGP 8.3.2, still with the same results. Also, there are much more Lint outputs that use paths to Gradle cache, like build/intermediates/lint_model/debug/generateDebugLintModel/module.xml
. For now the only solution for us was to disable cache for Lint tasks, but obviously we would like to restore it as fast as possible. If you need any additional info to debug this issue, please let me know.
sp...@google.com <sp...@google.com> #11
Thanks for the info.
I think the main underlying problem here is that the lint analysis task caches its output even when there is a LintError
, and I think the right fix is for AGP to throw an exception from the lint analysis task when there is a LintError
... This was discussed previously in the context of OOM
s; previously we decided not to throw an exception in cases other than OOM
s, but we didn't consider the case of rare exceptions getting cached as LintError
s in the build cache.
I think in your case, there is occasionally a NoSuchFileException
during lint analysis, and then the corresponding LintError
keeps showing up in subsequent builds because it gets cached in the build cache.
As far as what's causing the LintError
, I wonder if it's because of "gradle-home-cache-cleanup: true
" from #8... I'm not sure how that's implemented, but if it just cleans the Gradle home caches after each build, then it could cause that NoSuchFileException
if there is another build running simultaneously on the same machine.
Re: #9, I don't think the Gradle cache directory path is causing the issue because that file is not consumed by the lint analysis task.
mi...@allegro.com <mi...@allegro.com> #12
Regarding gradle-home-cache-cleanup: true
I can say with confidence that it has nothing to do with the issue, as it was occurring for a long time before we started using this feature. The feature itself cleans Gradle home artifacts that were not used during build before saving the cache to Github Actions cache.
sp...@google.com <sp...@google.com> #13
I think the right fix is for AGP to throw an exception from the lint analysis task when there is a LintError
This has been implemented and will be included in AGP 8.7.0-alpha08.
an...@google.com <an...@google.com> #14
Thank you for your patience while our engineering team worked to resolve this issue. A fix for this issue is now available in:
- Android Studio Ladybug | 2024.2.1 Canary 8
- Android Gradle Plugin 8.7.0-alpha08
We encourage you to try the latest update.
If you notice further issues or have questions, please file a new bug report.
Thank you for taking the time to submit feedback — we really appreciate it!
an...@google.com <an...@google.com> #15
Further fixes for this issue are now available in:
- Android Studio Ladybug | 2024.2.1 Canary 9
- Android Gradle Plugin 8.7.0-alpha09
We encourage you to try the latest update.
If you notice further issues or have questions, please file a new bug report.
kz...@gmail.com <kz...@gmail.com> #16 Restricted+
pa...@gmail.com <pa...@gmail.com> #17
For the record, I think this has now removed the ability:
- to observe LintError in the report XML/HTML/TXT/SARIF (i.e. no tooling can detect it), report task doesn't run because dependency fails.
- Knock-on: if there's a LintError, it has to be fixed BEFORE we can see and fix any other problems, even if there's just one rogue rule.
- Knock-on: can't see the formatted clear stack trace,
LINT_PRINT_STACKTRACE=true
has no effect any more - Knock-on: users have to read the logs of CI to understand the failure, even when there are artifacts/PR annotations are used.
- to suppress LintError in lint.xml (e.g. a check that only fails in one specific case, and otherwise useful)
- to baseline LintErrors (e.g. a check that only fails in one specific case, and otherwise useful)
Reported
Description
I only saw this once locally, so low priority at the moment
(scan has details on java, AGP, gradle versions)https://ge.androidx.dev/s/x2ecfl4oiiqig