[KSP2] @ColumnInfo(name=…) argument dropped on override property when a @property:-targeted annotation is also present (regression in 2.3.10)
- Dominant language
- Kotlin
- Stars
- 3.5k
- Forks
- 415
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 53
Description
## `@ColumnInfo(name = …)` argument is dropped on an `override` property when a `@property:`-targeted annotation is also present (KSP2, 2.3.10)
Hello! We run into a following issue when trying to bump ksp from 2.3.9 to 2.3.10:
### Summary
On KSP2, when a Room `@Entity` property is an `override` (from an interface) and carries **both**:
1. a Java-first annotation with an argument — `@ColumnInfo(name = "map_style")`, and
2. a use-site–targeted Kotlin annotation — `@property:MyAnnotation`
…KSP no longer surfaces the `@ColumnInfo` **`name` argument** to the Room processor. Room falls back to the Kotlin **property name** for the column, so the generated schema column is named after the property (`syncMapStyle`) instead of the declared `@ColumnInfo` name (`map_style`).
Removing the `@property:`-targeted annotation, or making the property non-`override`, makes the `name` argument reappear. So the trigger is the **combination** of `override` + `@ColumnInfo(name=…)` + a second `@property:` annotation on the same declaration.
This is a **silent** miscompile: no KSP error, no Room warning. The only symptom is a wrong column name in the generated `_Impl`, which surfaces at runtime as:
```
java.lang.IllegalStateException: Migration didn't properly handle: Trip(...RoomTrip).
Expected:
TableInfo{ ... columns include 'syncMapStyle', 'syncMapViewMode' ... }
Found:
TableInfo{ ... columns include 'map_style', 'view_mode' ... }
```
For any app with an existing on-disk database, this crashes on every upgrade.
### Environment
| | |
|---|---|
| KSP | `2.3.10` |
| Kotlin | `2.4.0` |
| Room | `2.8.4` |
| AGP | `9.2.1` |
| KSP mode | KSP2 |
Does **not** reproduce on KSP `2.3.9` (same Kotlin/Room) — generated column is correctly `map_style`. This is a regression in `2.3.10`.
### Reproduction
Minimal entity (full runnable MRE below / attached):
```kotlin
interface HasMapStyle {
var syncMapStyle: Int?
}
@Entity(tableName = "Trip")
class RoomTrip(
@PrimaryKey val uuid: String,
// ✅ resolves to column `end_date` — plain @ColumnInfo(name = …)
@ColumnInfo(name = "end_date")
var endDate: Long? = null,
// ❌ resolves to column `syncMapStyle` (property name) instead of `map_style`
// ONLY because a @property: annotation coexists with @ColumnInfo(name = …)
@ColumnInfo(name = "map_style")
@property:MyMarker
override var syncMapStyle: Int? = null,
) : HasMapStyle
@Retention(AnnotationRetention.SOURCE)
annotation class MyMarker
```
Generated `PolarstepsDatabase_Impl` `CREATE TABLE` (KSP 2.3.10):
```
CREATE TABLE IF NOT EXISTS `Trip` (... `end_date` REAL, `syncMapStyle` INTEGER, ...)
^^^^^^^^^^^^ should be `map_style`
```
Generated `_columnsTrip` TableInfo entries likewise omit `map_style` and instead register `syncMapStyle`.
### Expected
`@ColumnInfo(name = "map_style")` is honored regardless of the presence of an additional `@property:`-targeted annotation, i.e. the generated column is `map_style` (as it is on KSP 2.3.9, and as it is when the `@property:MyMarker` line is deleted).
Contributor guide
Research direction
The payload provides no repository file or test path. Start by running the minimal entity reproduction under KSP2 2.3.10 and compare it with 2.3.9, then trace KSP2 annotation-argument handling for overridden properties. Done is a regression test showing @ColumnInfo(name="map_style") remains visible alongside @property:MyMarker and the generated schema uses map_style.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kotlin
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100