{"record":{"id":"a3684abf7a4d699f","repo":"tauri-apps/tauri","slug":"missing-userinfo-for-channel-handler-this-is-a-tauri-issue","errorCode":null,"errorMessage":"missing userInfo for Channel handler. This is a Tauri issue","messagePattern":"missing userInfo for Channel handler\\. This is a Tauri issue","errorType":"exception","errorClass":"DecodingError","httpStatus":null,"severity":"error","filePath":"crates/tauri/mobile/ios-api/Sources/Tauri/Channel.swift","lineNumber":34,"sourceCode":"    let channelDef = try container.decode(String.self)\n\n    let components = channelDef.components(separatedBy: CHANNEL_PREFIX)\n    if components.count < 2 {\n      throw DecodingError.dataCorruptedError(\n        in: container,\n        debugDescription: \"Invalid channel definition from \\(channelDef)\"\n      )\n\n    }\n    guard let channelId = UInt64(components[1]) else {\n      throw DecodingError.dataCorruptedError(\n        in: container,\n        debugDescription: \"Invalid channel ID from \\(channelDef)\"\n      )\n    }\n\n    guard let handler = decoder.userInfo[channelDataKey] as? (UInt64, String) -> Void else {\n      throw DecodingError.dataCorruptedError(\n        in: container,\n        debugDescription: \"missing userInfo for Channel handler. This is a Tauri issue\"\n      )\n    }\n\n    self.id = channelId\n    self.handler = handler\n  }\n\n  func serialize(_ data: JsonValue) -> String {\n    do {\n      return try data.jsonRepresentation() ?? \"\\\"Failed to serialize payload\\\"\"\n    } catch {\n      return \"\\\"\\(error)\\\"\"\n    }\n  }\n\n  public func send(_ data: JsonObject) {","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/tauri-apps/tauri/blob/460ec35447493200d64290dd7f015d5a91d0fd58/crates/tauri/mobile/ios-api/Sources/Tauri/Channel.swift#L16-L52","documentation":"When decoding a Channel on iOS, Tauri reads the callback handler (a (UInt64, String) -> Void closure) from the decoder's userInfo under channelDataKey. If it is missing, the decoder was invoked without the userInfo entry Tauri's own infrastructure always supplies, so the code declares it a Tauri-internal bug and throws this DecodingError.","triggerScenarios":"Decoding a Channel with a JSONDecoder instance that was not set up by Tauri's IPC layer — i.e. decoder.userInfo[channelDataKey] contains no (UInt64, String) handler.","commonSituations":"Manually constructing a JSONDecoder and decoding a type containing a Channel in plugin code, calling decode outside the normal IPC dispatch path, or a Tauri version regression in the mobile API layer.","solutions":["Decode Channel-bearing payloads only through Tauri's normal IPC deserialization path, not a standalone JSONDecoder you create.","If you must decode manually, set decoder.userInfo[channelDataKey] to a (UInt64, String) -> Void handler before calling decode.","Update the iOS Tauri API dependency, since the message indicates an internal invariant break that may already be fixed upstream.","Report it to the Tauri repository with a reproducing plugin/webview setup if it occurs in stock usage."],"exampleFix":"// before\nlet decoder = JSONDecoder()\nlet value = try decoder.decode(MyArgs.self, from: data)\n// after: reuse Tauri's decoder that carries the channel handler\nlet value = try tauriProvidedDecoder.decode(MyArgs.self, from: data)","handlingStrategy":"type-guard","validationCode":"guard let handler = decoder.userInfo[Channel.channelDataKey] as? (UInt64, String) -> Void else { fatalError(\"decode via Tauri IPC path\") }","typeGuard":"let hasChannelHandler: (JSONDecoder) -> Bool = { $0.userInfo[Channel.channelDataKey] is (UInt64, String) -> Void }","tryCatchPattern":"do {\n  let value = try decoder.decode(MyArgs.self, from: data)\n} catch let DecodingError.dataCorruptedError(_, _, desc) where desc.contains(\"userInfo\") {\n  // fall back to Tauri-provided decoder\n}","preventionTips":["Never instantiate JSONDecoder yourself for payloads containing Channel.","Route all IPC decoding through Tauri's plugin dispatch layer.","Pin the iOS API package version alongside the Rust core version."],"tags":["ios","decoding","channel","internal-bug","userinfo"],"backgroundTag":"internal-invariant-violation","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"}