Fifth run cleared ktlint and detekt and failed compiling the GENERATED Kotlin:
'message' hides member of supertype 'Throwable' and needs an 'override'
modifier
My design, surfacing one layer down. CoreError's variants carried a `message`
field, and uniffi turns an error enum into exception classes extending
Throwable — which already has `message`.
`#[uniffi(flat_error)]` is the right fix rather than renaming the field.
Renaming would dodge the collision and leave `e.message` null on the Kotlin side,
so every call site would have to know which variant it caught just to read the
text. Flat passes the Display string to the Throwable constructor, where Kotlin
expects it, and costs nothing that matters: each variant is still its own
subclass, so `catch (e: CoreException.NotLinked)` still works and a `when` is
still exhaustive. Only the fields stop crossing, and for every variant that has
one the field IS the Display string.
Confirmed by generating the bindings and reading them:
sealed class CoreException(message: String): kotlin.Exception(message) {
class NotLinked(message: String) : CoreException(message)
class Store(message: String) : CoreException(message)
class Network(message: String) : CoreException(message)
}
That check is worth keeping. thoughtsync-ffi already builds a HOST .so as part
of the workspace, and `--library` mode reads metadata straight out of it — so
the exact Kotlin the Android lane will compile can be generated and inspected
here, with no Android toolchain involved. It also let me verify the app's call
sites against the real generated API rather than against my assumptions about
uniffi's naming: ThoughtSync(dataDir), createNote(draft), listNotes(query),
Note.displayTitle, and NoteDraft/NoteQuery's parameter names all match.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>