Skip to content

Fix KSP2 "PSI has changed since creation" errors#1396

Merged
elihart merged 5 commits intomasterfrom
eli-fix_ksp_psi_change_issue
Jan 23, 2026
Merged

Fix KSP2 "PSI has changed since creation" errors#1396
elihart merged 5 commits intomasterfrom
eli-fix_ksp_psi_change_issue

Conversation

@elihart
Copy link
Contributor

@elihart elihart commented Jan 13, 2026

Summary

  • Fixes critical crashes in KSP2 where accessing elements from previous processing rounds causes KaInvalidLifetimeOwnerAccessException: PSI has changed since creation
  • This issue affects any project with multi-round annotation processing (deferred elements from round 1 accessed in round 2+)

Problem

In KSP2, PSI elements become invalid after each processing round. Epoxy's processor held references to stale KSP types/elements via:

  • Cached XElement objects in KspResourceScanner
  • XType stored in PackageModelViewSettings
  • Lazy properties in GeneratedModelInfo, Type, and other classes
  • Stale memoizer references captured in round 1, accessed in round 2+

Solution

Applied fixes across the processor:

  1. Cache Invalidation: Added clearCachesForNewRound() to KspResourceScanner to clear element caches between rounds
  2. Store Stable Identifiers: Changed PackageModelViewSettings to store defaultBaseModelClassName: String instead of XType
  3. Pass Current Context: Updated method signatures throughout the codebase to accept currentMemoizer: Memoizer parameter instead of relying on stale captured references:
    - GeneratedModelInfo.isSuperClassAlsoGenerated()
    - GeneratedModelInfo.safeSuperClassElement()
    - GeneratedModelInfo.originatingElements()
    - GeneratedModelWriter.modelImplementsBindWithDiff()
    - ConfigManager.getDefaultBaseModel()
  4. Fresh Type Resolution: Changed Memoizer.getMethodsReturningClassType() to accept classQualifiedName: String and resolve types fresh each round
  5. Eager Initialization: Changed Type.kt's typeName and typeEnum from lazy to eager initialization to capture values when xType is still fresh
  6. Exception Handling: Added try-catch in Memoizer.implementsModelCollector() for cases where XProcessing library has internal stale state

@elihart elihart merged commit 4ee6b50 into master Jan 23, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant