Skip to content

Commit 2074bba

Browse files
committed
npx skills add huanshankeji/kotlin-skills
1 parent 6218270 commit 2074bba

2 files changed

Lines changed: 171 additions & 0 deletions

File tree

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
---
2+
name: kotlin-debugging-unresolved-reference-file-clash
3+
description: >
4+
Diagnoses and fixes Kotlin JVM "Unresolved reference" compilation errors
5+
caused by file facade class name clashes. Use when you encounter "Unresolved
6+
reference" or "can't resolve" errors in a Kotlin JVM or Kotlin Multiplatform
7+
project where dependencies appear correct, especially after adding, moving,
8+
or renaming Kotlin files with top-level declarations.
9+
license: Apache-2.0
10+
metadata:
11+
author: huanshankeji
12+
version: "1.0.0"
13+
---
14+
15+
# Debugging "Unresolved reference" errors caused by Kotlin file facade clashes
16+
17+
## Background: Kotlin file facades on JVM
18+
19+
When a Kotlin file contains top-level declarations (functions, properties, or
20+
type aliases), the Kotlin/JVM compiler generates a **file facade** class in the
21+
output bytecode. The facade class is named `<FileName>Kt` (e.g., `Utils.kt`
22+
produces `UtilsKt.class`) and is placed in the package declared in the file.
23+
24+
If two Kotlin files with the **same file name** and the **same package** end up
25+
on the same compilation classpath — even if they reside in different source
26+
directories, source sets, or modules — their generated file facade classes
27+
**clash**. Instead of a clear "duplicate class" message, the Kotlin compiler
28+
often reports **misleading "Unresolved reference"** errors on symbols that are
29+
actually defined correctly. This makes the root cause difficult to identify.
30+
31+
## When to use
32+
33+
Apply this debugging procedure when **all** of the following are true:
34+
35+
1. The compiler reports `Unresolved reference: <symbol>` or similar "can't
36+
resolve" errors.
37+
2. The referenced symbol **does** exist in the source code with correct
38+
visibility and is in the expected dependency.
39+
3. Project dependencies and imports **look correct** — no obvious missing
40+
dependency, typo, or visibility issue.
41+
42+
These errors frequently occur after:
43+
44+
- Adding a new Kotlin file that happens to share a name and package with an
45+
existing file in another source set or module.
46+
- Moving or renaming files across source sets (e.g., `commonMain`
47+
`jvmMain` in Kotlin Multiplatform) without cleaning up the old location.
48+
- Refactoring that introduces files with common names (e.g., `Icons.kt`,
49+
`Utils.kt`, `Extensions.kt`) in the same package across modules.
50+
51+
## Diagnostic steps
52+
53+
### Step 1: Search for duplicate file names in the same package
54+
55+
Search the project for Kotlin source files (`.kt`) that share the **same file
56+
name** and have the **same `package` declaration**. Pay special attention to
57+
files across different source roots or source sets that are compiled together
58+
for the same target (e.g., `src/main/kotlin` and another source directory both
59+
feeding into a JVM compilation).
60+
61+
```bash
62+
# Example: find all files named "Icons.kt" in the project
63+
find . -name "Icons.kt" -type f
64+
```
65+
66+
Then compare the `package` declarations in each result. If two or more files
67+
share the same file name and the same package, you have found the clash.
68+
69+
### Step 2: Verify the clash is the root cause
70+
71+
Temporarily rename one of the clashing files (e.g., `Icons.kt`
72+
`Icons2.kt`) and rebuild. If the "Unresolved reference" errors disappear, the
73+
file facade clash was the root cause.
74+
75+
### Step 3: Apply a fix
76+
77+
Choose one of the following fixes:
78+
79+
#### Option A: Rename the file (recommended)
80+
81+
Rename one of the clashing files to a unique name. This is the simplest and
82+
most reliable fix.
83+
84+
```
85+
# Before (clash)
86+
moduleA/src/main/kotlin/com/example/Icons.kt
87+
moduleB/src/main/kotlin/com/example/Icons.kt
88+
89+
# After (fixed)
90+
moduleA/src/main/kotlin/com/example/Icons.kt
91+
moduleB/src/main/kotlin/com/example/PlatformIcons.kt
92+
```
93+
94+
#### Option B: Change the package
95+
96+
Move one of the files to a different package so the fully qualified facade
97+
class names differ.
98+
99+
#### Option C: Use `@file:JvmName` (advanced)
100+
101+
If renaming the file is undesirable, annotate one of the files with
102+
`@file:JvmName` to give its facade class a different JVM name:
103+
104+
```kotlin
105+
@file:JvmName("PlatformIcons")
106+
107+
package com.example
108+
109+
// top-level declarations...
110+
```
111+
112+
This changes the generated class from `IconsKt.class` to
113+
`PlatformIcons.class`, resolving the clash. Note that this only affects the
114+
JVM facade name; Kotlin callers are unaffected.
115+
116+
### Step 4: Clean and rebuild
117+
118+
After applying the fix, perform a clean build to ensure no stale class files
119+
remain:
120+
121+
```bash
122+
./gradlew clean build
123+
```
124+
125+
## Common scenarios
126+
127+
### Kotlin Multiplatform projects
128+
129+
In Kotlin Multiplatform projects, `commonMain`, `jvmMain`, and other source
130+
sets are compiled together for JVM targets. A file `Utils.kt` with package
131+
`com.example` in `commonMain` and another `Utils.kt` with the same package in
132+
`jvmMain` will clash. A conventional solution here is to rename the
133+
platform-specific file with a platform suffix, e.g., `Utils.jvm.kt`.
134+
135+
### Multi-module Gradle projects
136+
137+
When module A depends on module B and both contain a file with the same name
138+
and package containing top-level declarations, the file facades collide on the
139+
classpath.
140+
141+
### After adding or moving files
142+
143+
AI coding agents and developers frequently trigger this when adding new files
144+
with common names (e.g., `Icons.kt`, `Extensions.kt`, `Helpers.kt`) without
145+
checking whether a same-named file already exists in the same package elsewhere
146+
in the project.
147+
148+
## Guardrails
149+
150+
- Do **not** assume the error is a missing dependency or import if the symbol
151+
clearly exists in the source.
152+
- Do **not** add redundant dependencies or imports to try to fix the error
153+
without first checking for file clashes.
154+
- Before creating a new Kotlin file with top-level declarations, search the
155+
project for existing files with the same name in the same package.
156+
157+
## References
158+
159+
- [Kotlin documentation: Packages and imports](https://kotlinlang.org/docs/packages.html)
160+
- [Kotlin documentation: Java interop — Package-level functions](https://kotlinlang.org/docs/java-to-kotlin-interop.html#package-level-functions)
161+
- [KT-83413: Misleading "Unresolved reference" errors caused by file facade class name clashes](https://youtrack.jetbrains.com/issue/KT-83413)

skills-lock.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"version": 1,
3+
"skills": {
4+
"kotlin-debugging-unresolved-reference-file-clash": {
5+
"source": "huanshankeji/kotlin-skills",
6+
"sourceType": "github",
7+
"computedHash": "d5173ec93bdf44b3eda8c4ccf1f4e59ce9eb8fad43187dc781bdd8050d62db8e"
8+
}
9+
}
10+
}

0 commit comments

Comments
 (0)