tauri-apps/tauri · error · Error
unexpected channel value $channelDef
Error message
unexpected channel value $channelDef
What it means
The Android ChannelDeserializer strips the channel prefix from the incoming channel definition string and parses the remainder as a Long callback ID. If the remainder is not a valid Long, it throws this Error with the offending string embedded. This means the webview sent a channel value in an unexpected format.
Solutions
- Verify the channel definition string logged in the error and ensure it contains a numeric ID after the channel prefix.
- Keep the Tauri Android runtime and Rust core versions in sync so the channel wire format matches.
- Replace any hand-built channel identifiers in plugin code with channels created via the official Channel/IPC APIs.
- Clear app state and reload the webview to rule out a stale cached message after an app update.
Example fix
// before: hand-rolled channel string
window.__TAURI_INTERNALS__.invoke('cmd', { ch: '__CHANNEL__:' + arbitraryText })
// after: use a real channel object
const ch = new Channel((data) => console.log(data))
invoke('cmd', { ch }) Defensive patterns
Strategy: validation
Validate before calling
fun isValidChannelDef(def: String) = def.removePrefix(CHANNEL_PREFIX).toLongOrNull() != null
Try / catch
try {
channelManager.deserialize(json)
} catch (e: Error) {
if (e.message?.startsWith("unexpected channel value") == true) {
// resync versions / re-register channel
}
} Prevention
- Use Channel objects from the plugin API rather than hand-crafted strings.
- Match Android runtime and Rust core versions.
- Re-register channels after webview reloads before issuing new commands.
When it happens
Trigger: deserialize() receives a JSON string whose content after the CHANNEL_PREFIX is null/blank/non-numeric, or exceeds Long range, so toLongOrNull() returns null.
Common situations: Rust/JS and Android plugin versions disagree on the channel serialization format, hand-constructed channel strings from custom plugin code, or corrupted IPC messages after a hot reload of the webview.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Invalid channel ID from \(channelDef)
- No command found for plugin
- Not all items are instances of the given type
- Invalid channel definition from \(channelDef)
- the plugin manager has no activity to launch from
AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18).
Data as JSON: /api/errors/bb95e4889190a406.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tauri/mobile/android/src/main/java/app/tauri/plugin/Channel.kt:20
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
package app.tauri.plugin
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.ObjectMapper
const val CHANNEL_PREFIX = "__CHANNEL__:"
internal class ChannelDeserializer(val sendChannelData: (channelId: Long, data: String) -> Unit, private val objectMapper: ObjectMapper): JsonDeserializer<Channel>() {
override fun deserialize(
jsonParser: JsonParser?,
deserializationContext: DeserializationContext
): Channel {
val channelDef = deserializationContext.readValue(jsonParser, String::class.java)
val callback = channelDef.substring(CHANNEL_PREFIX.length).toLongOrNull() ?: throw Error("unexpected channel value $channelDef")
return Channel(callback, { res -> sendChannelData(callback, res) }, objectMapper)
}
}
class Channel(val id: Long, private val handler: (data: String) -> Unit, private val objectMapper: ObjectMapper) {
fun send(data: JSObject) {
handler(PluginResult(data).toString())
}
fun sendObject(data: Any) {
handler(objectMapper.writeValueAsString(data))
}
}
View on GitHub (pinned to 460ec35447)