Troubleshooting

This chapter collects common setup, query, and runtime troubleshooting steps.

Use this page to check setup, SQL generation, and runtime behavior.

Resolve dependency coordinates

Use the stable Kronos version from the docs macro in docs pages and a current stable version for third-party drivers.

build.gradle.kts

dependencies {
    implementation("com.kotlinorm:kronos-core:0.4.0")
    implementation("com.kotlinorm:kronos-jdbc-wrapper:0.4.0")
    implementation("com.mysql:mysql-connector-j:<latest-stable>")
}

Replace <latest-stable> with the current stable driver version for your database and JDK.

For a complete setup, see 📚Quick Start and 📚Connect to DB.

Compiler plugin setup needs a check

Kronos compile-time support runs during Kotlin compilation. Compile the module that declares KPojo classes or writes Kronos DSL calls, then check the build output.

Gradle

./gradlew :app:compileKotlin

output

[Kronos] Kronos compiler plugin K2 initialized
BUILD SUCCESSFUL

Apply the Kronos Gradle or Maven plugin to each source set that declares entities or query DSL. The complete build-tool examples and source-set rule are in 📚Compiler Plugins.

Check KPojo generated members

Generated members such as __tableName, toDataMap(), __columns, and dynamic accessors are available after the source set is compiled with Kronos support.

kotlin

val user = User(id = 7, name = "Ada")

println(user.__tableName)
println(user.toDataMap())
println(user.__columns.map { it.name })

output

tb_user
{id=7, name=Ada}
[id, name]

When runtime output mentions __tableName must be overridden by the compiler plugin, compile the module with the Kronos plugin active and reimport the project in the IDE. See 📚Check generated KPojo members for the full check.

Projection or scalar subquery diagnostics appear

Projection result fields need stable names. Give function, aggregate, window, raw SQL, and scalar subquery select items an alias.

alias

User()
    .select { [it.id, f.length(it.name).alias("nameLength")] }
    .toList()

Scalar subqueries used as values need one selected field and limit(1).

scalar

User()
    .select { user ->
        [
            user.id,
            Order()
                .select { it.amount }
                .where { it.userId == user.id }
                .limit(1)
                .alias("lastAmount")
        ]
    }
    .toList()

The diagnostic codes KRONOS_SELECT_ITEM_REQUIRES_ALIAS, KRONOS_SCALAR_SUBQUERY_REQUIRES_LIMIT, and KRONOS_SCALAR_SUBQUERY_REQUIRES_SINGLE_COLUMN are listed in 📚Fix common diagnostics. Query-shape examples are in 📚Projection and 📚Subqueries.

Configure the data source

Kronos ORM operations need a configured Kronos.dataSource.

kotlin

val wrapper = KronosJdbcWrapper(dataSource)

Kronos.dataSource = { wrapper }

val users = User().select().toList()

When a command needs a specific data source, call it through the wrapper.

wrapper

val users = User()
    .select()
    .toList(wrapper)

Dialect output looks different

Kronos renders SQL from KronosDataSourceWrapper.dbType. Print the wrapper values when SQL quoting or pagination is unexpected.

kotlin

val wrapper = KronosJdbcWrapper(dataSource)

println(wrapper.dbType)
println(wrapper.sqlDialect)

For quoting, pagination, upsert, DDL, and function examples, see 📚Database Dialect Support.

Check where() conditions

select() alone chooses the table and projection. Empty where() applies query-by-example from non-null queryable fields.

select

User(id = 1).select()
// SELECT ... FROM user

User(id = 1).select().where()
// WHERE id = 1

A lambda controls that where call directly.

lambda

User(id = 1)
    .select()
    .where { it.name == "Ada" }
// WHERE name = 'Ada'

For where composition rules, see 📚Conditions.

Review DataGuard write and DDL protection

DataGuard rejects full-table writes and protected table operations before execution.

result

DataGuardPlugin.enable()

User()
    .delete()
    .execute()

error

UnsupportedOperationException: Delete operation is not allowed.

Add a condition or configure an allow rule for planned maintenance.

allow

DataGuardPlugin.enable {
    deleteAll {
        allow {
            tableName = "tmp_import_error"
        }
    }
}

For policy examples, see 📚DataGuard.

Logic delete or optimistic lock changes the SQL

Logic delete and optimistic lock annotations add write conditions or assignments based on KPojo metadata.

kotlin

data class User(
    @PrimaryKey
    var id: Int? = null,
    @LogicDelete
    @Default("0") // @Default("false") for Postgres
    var deleted: Boolean? = null,
    @Version
    var version: Int? = null
) : KPojo

For the mutation behavior, see 📚Logic Delete and 📚Optimistic Lock.

View generated SQL

Use the task-building APIs when a page documents a build...Task form.

kotlin

val task = Kronos.dataSource.table.buildCreateTableAsSelectTask(
    OrderArchive(),
    Order().select { [it.id, it.userId] }
)

println(task.sql)
println(task.paramMap)

For SQL generated from select, join, subquery, and CTAS, see 📚Subqueries and 📚Create Table As Select.

Codegen or IDE plugin needs a starting point

Use Codegen when database metadata should produce KPojo files.

codegen

@file:DependsOn("com.kotlinorm:kronos-codegen:0.4.0")

Use the KEFS setup page for editor support and diagnostics.

pages

Resources -> Code Generator
Resources -> IDE Support with KEFS

See 📚Code Generator and 📚IDE Support with KEFS.