---
name: build-errors-kotlin
description: >
  Resolución de errores de compilación Kotlin: kotlinc, Gradle KTS, Android
  build y Jetpack Compose. Incluye errores de Hilt, recursos Android y
  conflictos de versiones en Gradle.
  Cargar cuando un build Kotlin/Android falle o haya errores de compilación.
version: "1.0.0"
herramientasPermitidas: [Read, Bash, Grep]
exclusiones:
  - "No cargar para bugs de UI en Compose en runtime (composables que renderizan mal) cuando el build pasa — si `./gradlew assembleDebug` compila pero la pantalla no se ve bien, es un error de lógica de UI; cargar `kotlin-compose`."
  - "No cargar para fallos de tests unitarios Kotlin (JUnit, Kotest assertions) cuando el build compila — si el build pasa pero los tests fallan por valores incorrectos, es un error de lógica de tests."
  - "No cargar para errores de Hilt en runtime (NullPointerException al inyectar en producción) cuando el build compila — si el APK se genera pero crashea por DI en runtime, revisar la configuración de Hilt directamente."
  - "No cargar para diseñar la arquitectura del proyecto Android/Kotlin desde cero — si la pregunta es cómo organizar módulos, capas y features en un proyecto multi-módulo, cargar `kotlin-experto` o `kotlin-patrones`."
evolvable: true  # default para skill estandar
---
# Build Errors Kotlin — Diagnóstico y Solución

## Cuándo NO cargar

- El build compila pero los Composables renderizan mal en pantalla — es un error de lógica de UI; cargar `kotlin-compose`.
- Los tests Kotest/JUnit fallan en assertions aunque compilan — es un error de lógica de tests.
- La pregunta es cómo organizar la arquitectura Android multi-módulo — para diseño cargar `kotlin-experto`.

## Cuándo cargar

- `./gradlew build` o `./gradlew assembleDebug` falla
- Errores de kotlinc (type mismatch, unresolved reference)
- Errores del compilador de Compose (stability, composable context)
- Conflictos de versiones en Gradle KTS (`buildscript`, `plugin resolution`)
- Errores de Hilt (missing binding, component hierarchy)
- Errores de recursos Android (R class, manifest merge)

---

## Kotlinc — Errores del Compilador

### `type mismatch: inferred type is X but Y was expected`

**Causa**: el tipo inferido no coincide con el esperado. Frecuente con nullable vs non-null.

```kotlin
// MAL
fun obtenerNombre(): String {
    val nombre: String? = buscarEnDB()
    return nombre  // error: String? no es String
}

// BIEN — opcion 1: null check con throw
fun obtenerNombre(): String {
    return buscarEnDB() ?: throw IllegalStateException("Nombre no encontrado")
}

// BIEN — opcion 2: retornar nullable en la firma
fun obtenerNombre(): String? = buscarEnDB()

// BIEN — opcion 3: valor por defecto
fun obtenerNombre(): String = buscarEnDB() ?: "Sin nombre"
```

### `unresolved reference: X`

**Causa**: clase, función o propiedad no importada, o dependencia Gradle faltante.

```kotlin
// MAL — usar Flow sin import ni dependencia
val flujo: Flow<Int> = flow { emit(1) }  // unresolved: Flow

// BIEN — agregar import explícito
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

// En build.gradle.kts si falta la dependencia:
dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
}
```

### `none of the following candidates is applicable because of receiver type mismatch`

**Causa**: se llama una función de extensión sobre el tipo incorrecto.

```kotlin
// MAL — trim() es para String, no para String?
fun limpiar(texto: String?): String {
    return texto.trim()  // error: trim() no existe en String?
}

// BIEN
fun limpiar(texto: String?): String {
    return texto?.trim() ?: ""
}
```

---

## Gradle KTS — Errores de Configuración

### `Unresolved reference` en build.gradle.kts

**Causa**: el DSL de Gradle KTS es estricto con tipos. Diferencias respecto a Groovy.

```kotlin
// MAL — sintaxis Groovy en KTS
android {
    compileSdkVersion 34      // error: funcion deprecated en KTS
    buildToolsVersion "34.0"  // puede fallar
}

// BIEN — DSL moderno en KTS
android {
    compileSdk = 34
    defaultConfig {
        minSdk = 24
        targetSdk = 34
    }
}
```

### Plugin no encontrado en `plugins {}` block

```kotlin
// MAL — plugin sin version ni alias de catalog
plugins {
    id("com.google.dagger.hilt.android")  // error si no hay version
}

// BIEN — con versión explícita
plugins {
    id("com.google.dagger.hilt.android") version "2.51.1" apply false
}

// BIEN — con version catalog (libs.versions.toml)
plugins {
    alias(libs.plugins.hilt)
}
```

### `Could not resolve com.example:lib:1.0` — dependencia no encontrada

```kotlin
// Verificar repositorios en settings.gradle.kts
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        // Si es repositorio privado:
        maven {
            url = uri("https://repo.empresa.com/maven")
            credentials {
                username = providers.gradleProperty("repoUser").get()
                password = providers.gradleProperty("repoPass").get()
            }
        }
    }
}
```

---

## Android Build — Errores de Recursos y Manifest

### `error: cannot find symbol class R`

**Causa**: el archivo R.java no se generó correctamente o hay error en un recurso XML.

```bash
# Diagnostico: limpiar y reconstruir
./gradlew clean assembleDebug

# Ver error raiz del recurso XML
./gradlew assembleDebug --stacktrace 2>&1 | grep "error:"

# Causas comunes:
# - Nombre de recurso con guion (usar guion_bajo en su lugar)
# - Etiqueta XML mal cerrada en layout
# - Valor de color/dimension con formato incorrecto
```

### Manifest merge conflict

```xml
<!-- Error típico: herramientas:node="merge" conflicto de atributo -->
<!-- En el AndroidManifest.xml de la app, forzar valor -->
<activity
    android:name=".MainActivity"
    tools:node="merge"
    tools:replace="android:theme">
```

### `D8: Dex file larger than 64K methods` (MultiDex)

```kotlin
// En build.gradle.kts del modulo app:
android {
    defaultConfig {
        multiDexEnabled = true
    }
}
dependencies {
    implementation("androidx.multidex:multidex:2.0.1")
}
```

---

## Jetpack Compose — Errores del Compilador

### `@Composable invocations can only happen from the context of a @Composable function`

**Causa**: se llama un Composable desde una lambda no anotada o desde código no-Compose.

```kotlin
// MAL
fun configurarUI() {
    MiComponente()  // error: no es contexto Composable
}

// MAL — lambda sin anotación
val accion: () -> Unit = {
    MiComponente()  // error
}

// BIEN — solo dentro de funciones @Composable
@Composable
fun PantallaInicio() {
    MiComponente()  // correcto
}
```

### Stability issues — `Parameter X is not stable`

**Causa**: el compilador de Compose no puede inferir la estabilidad de un tipo,
lo que deshabilita el smart recomposition.

```kotlin
// MAL — clase mutable sin anotación
data class Estado(var contador: Int)  // var hace al tipo inestable

// BIEN — opción 1: usar val (inmutable)
data class Estado(val contador: Int)

// BIEN — opción 2: anotación explícita si la clase es external
@Stable
class EstadoExterno(private val wrapped: ExternalClass)

// BIEN — opcion 3: en compose_compiler_config.conf marcar clases externas
// ver: https://developer.android.com/develop/ui/compose/performance/stability/fix
```

---

## Hilt — Errores de Inyección de Dependencias

### `[Hilt] Missing binding for X`

**Causa**: Hilt no sabe cómo proveer el tipo solicitado.

```kotlin
// MAL — interfaz sin @Binds ni @Provides
interface Repositorio
class RepositorioImpl @Inject constructor() : Repositorio

// Para que Hilt resuelva la interfaz, se necesita un modulo:
@Module
@InstallIn(SingletonComponent::class)
abstract class RepositorioModule {
    @Binds
    @Singleton
    abstract fun bindRepositorio(impl: RepositorioImpl): Repositorio
}
```

### `@HiltAndroidApp` no encontrado

```kotlin
// En Application class — sin esto Hilt no inicializa
@HiltAndroidApp
class MiAplicacion : Application()

// En AndroidManifest.xml:
// <application android:name=".MiAplicacion" ...>
```

---

## Gotchas / Errores comunes no obvios

- **`./gradlew build` falla con "Could not resolve com.android.tools.build:gradle:X.Y.Z"** aunque la versión existe en Maven Central: el repositorio `google()` no está declarado en `settings.gradle.kts` antes de `mavenCentral()`. Causa: AGP (Android Gradle Plugin) está en el repositorio de Google, no en Maven Central; si `google()` no está o está en el orden incorrecto, la resolución falla. Solución: asegurarse que `settings.gradle.kts` tiene `google()` primero en el bloque `pluginManagement.repositories` Y en `dependencyResolutionManagement.repositories`.
- **Compose BOM actualizado produce error `Unresolved reference: LazyColumn`** aunque la función existe en la misma versión de Compose UI: el BOM alinea versiones pero el IDE puede cachear las versiones antiguas del árbol de dependencias. Causa: el cache de Gradle tiene la versión anterior del artefacto `compose.foundation` sin invalidar. Solución: ejecutar `./gradlew cleanBuildCache` y sincronizar el proyecto en Android Studio — si persiste, verificar con `./gradlew :app:dependencies | grep compose-foundation` que la versión del BOM es la que se espera.
- **Hilt `@Binds` en un módulo abstracto produce "MissingBinding" aunque la implementación existe**: la clase `RepositorioImpl` está en un feature module diferente al módulo donde está instalado el componente Hilt. Causa: los módulos Hilt solo ven las dependencias del componente en el que están instalados (`SingletonComponent`, `ActivityComponent`, etc.) — las dependencias entre feature modules no se ven automáticamente. Solución: instalar el módulo de Hilt con `@InstallIn(SingletonComponent::class)` en el feature module que provee la implementación, asegurando que ese módulo tiene dependencia del módulo que lo necesita.
- **`kotlinc` compila el módulo de library pero el módulo de app falla con "unresolved reference"** apuntando a una clase de la library**: la library tiene `internal` en la clase en lugar de `public`. Causa: `internal` en Kotlin restringe la visibilidad al mismo módulo de Kotlin — una clase `internal` en `:core` no es visible en `:app`. Solución: cambiar la visibilidad a `public` (o dejar sin modificador, que es `public` por defecto en Kotlin) y revisar que la clase no tiene restricciones de API pública que justifiquen `internal`.

## Checklist de Diagnóstico

- [ ] Ejecutar `./gradlew build --stacktrace` para ver la causa raíz del error.
- [ ] `./gradlew dependencies` para ver el árbol de dependencias y conflictos.
- [ ] Limpiar caché de Gradle si hay errores inexplicables: `./gradlew cleanBuildCache`.
- [ ] Verificar compatibilidad de versiones en `libs.versions.toml` (Kotlin, AGP, Compose BOM).
- [ ] Para errores de Compose: habilitar reportes del compilador con `reportsDestination`.
- [ ] Si el error es de Hilt: revisar que `@HiltAndroidApp` está en Application.
- [ ] Para R class: revisar XMLs de recursos por errores de sintaxis o nombres inválidos.
- [ ] `./gradlew lint` para detectar problemas antes de compilar.
