State<List<User>?> is not a delegate: top 3 errors and solutions in Kotlin

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Silent panic: when Kotlin screams that State cannot be a delegate

\n\n

You are writing code in Kotlin, using Jetpack Compose, everything is going according to plan. And suddenly — bam! — the compiler outputs a message that makes a beginner's stomach turn cold: Type 'State<List<User>?>' has no method 'getValue(Nothing?, KProperty<*>)' and thus it cannot serve as a delegate. It sounds like a verdict, but in reality it's just a cry for help from your code. Let's figure out what it wants to say and how to make friends with it.

\n\n

This error is one of the most popular on Stack Overflow (thousands of views!), and it haunts developers who are just starting to learn delegated properties in Kotlin. In this article, we will not just translate the error message, but show three real situations when it occurs and give working solutions. You will learn how to properly use StateFlow in Compose, how not to get confused with Kotlin delegates, and why LiveData sometimes behaves unexpectedly.

\n\n

What is a delegate in Kotlin and why does State not become one?

\n\n

First, a quick primer. Delegated properties in Kotlin (the by keyword) allow you to move the getter and setter logic to a separate object. For example:

\n\n
var name: String by Delegates.observable("") { prop, old, new ->\n    println("$old → $new")\n}\n
\n\n

For an object to be a delegate, it must implement the getValue() and possibly setValue() methods with a specific signature. The error Type 'State<List<User>?>' has no method 'getValue(Nothing?, KProperty<*>)' says exactly this: your object of type State<List<User>?> does not have a suitable getValue method. The compiler cannot use it as a delegate.

\n\n

Now let's move on to three specific scenarios where this error most often occurs.

\n\n

Error 1: Confusion with by and assigning StateFlow

\n\n

The most common case is when a developer tries to use by to assign a StateFlow in a ViewModel, but does it incorrectly. Look at this code:

\n\n
// ❌ Error! This is not allowed\nclass MyViewModel : ViewModel() {\n    private val _users = MutableStateFlow<List<User>?>(null)\n    val users: StateFlow<List<User>?> by _users  // Error!\n}\n
\n\n

Here, _users is a MutableStateFlow, and we are trying to make it a delegate for the users property. But StateFlow does not implement getValue for Kotlin properties. It is not a delegate, it is a reactive stream.

\n\n

Solution: use asStateFlow()

\n\n

The correct way is not to delegate, but to convert:

\n\n
// ✅ Correct\nclass MyViewModel : ViewModel() {\n    private val _users = MutableStateFlow<List<User>?>(null)\n    val users: StateFlow<List<User>?> = _users.asStateFlow()\n}\n
\n\n

The asStateFlow() method creates an immutable copy that is safe to expose externally. No delegates, no errors.

\n\n

Error 2: Using by with LiveData in Compose

\n\n

The second most popular situation is an attempt to use LiveData directly with by in Jetpack Compose. Developers coming from the View system world are used to LiveData and try to apply the same approach:

\n\n
// ❌ Error!\n@Composable\nfun UserList(viewModel: MyViewModel) {\n    val users: List<User>? by viewModel.users  // Error!\n    // ...\n}\n
\n\n

Here, viewModel.users has type LiveData<List<User>?>. And LiveData is not a delegate for Compose properties. The compiler again gives the same error: Type 'LiveData<List<User>?>' has

Blogs

Book Recommendations