{"record":{"id":"bb95e4889190a406","repo":"tauri-apps/tauri","slug":"unexpected-channel-value-channeldef","errorCode":null,"errorMessage":"unexpected channel value $channelDef","messagePattern":"unexpected channel value \\$channelDef","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/tauri/mobile/android/src/main/java/app/tauri/plugin/Channel.kt","lineNumber":20,"sourceCode":"// SPDX-License-Identifier: Apache-2.0\n// SPDX-License-Identifier: MIT\n\npackage app.tauri.plugin\n\nimport com.fasterxml.jackson.core.JsonParser\nimport com.fasterxml.jackson.databind.DeserializationContext\nimport com.fasterxml.jackson.databind.JsonDeserializer\nimport com.fasterxml.jackson.databind.ObjectMapper\n\nconst val CHANNEL_PREFIX = \"__CHANNEL__:\"\n\ninternal class ChannelDeserializer(val sendChannelData: (channelId: Long, data: String) -> Unit, private val objectMapper: ObjectMapper): JsonDeserializer<Channel>() {\n  override fun deserialize(\n    jsonParser: JsonParser?,\n    deserializationContext: DeserializationContext\n  ): Channel {\n    val channelDef = deserializationContext.readValue(jsonParser, String::class.java)\n    val callback = channelDef.substring(CHANNEL_PREFIX.length).toLongOrNull() ?: throw Error(\"unexpected channel value $channelDef\")\n    return Channel(callback, { res -> sendChannelData(callback, res) }, objectMapper)\n  }\n}\n\nclass Channel(val id: Long, private val handler: (data: String) -> Unit, private val objectMapper: ObjectMapper) {\n  fun send(data: JSObject) {\n    handler(PluginResult(data).toString())\n  }\n\n  fun sendObject(data: Any) {\n    handler(objectMapper.writeValueAsString(data))\n  }\n}\n","sourceCodeStart":2,"sourceCodeEnd":34,"githubUrl":"https://github.com/tauri-apps/tauri/blob/460ec35447493200d64290dd7f015d5a91d0fd58/crates/tauri/mobile/android/src/main/java/app/tauri/plugin/Channel.kt#L2-L34","documentation":"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.","triggerScenarios":"deserialize() receives a JSON string whose content after the CHANNEL_PREFIX is null/blank/non-numeric, or exceeds Long range, so toLongOrNull() returns null.","commonSituations":"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.","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."],"exampleFix":"// before: hand-rolled channel string\nwindow.__TAURI_INTERNALS__.invoke('cmd', { ch: '__CHANNEL__:' + arbitraryText })\n// after: use a real channel object\nconst ch = new Channel((data) => console.log(data))\ninvoke('cmd', { ch })","handlingStrategy":"validation","validationCode":"fun isValidChannelDef(def: String) = def.removePrefix(CHANNEL_PREFIX).toLongOrNull() != null","typeGuard":null,"tryCatchPattern":"try {\n  channelManager.deserialize(json)\n} catch (e: Error) {\n  if (e.message?.startsWith(\"unexpected channel value\") == true) {\n    // resync versions / re-register channel\n  }\n}","preventionTips":["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."],"tags":["android","kotlin","channel","ipc","invalid-id"],"backgroundTag":"invalid-argument-format","analyzedSha":"460ec35447493200d64290dd7f015d5a91d0fd58","analyzedAt":"2026-09-18T23:55:51.277Z","contentChangedAt":"2026-09-18T23:55:51.277Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}