tauri-apps/tauri · error · DecodingError
Invalid channel definition from \(channelDef)
Error message
Invalid channel definition from \(channelDef)
What it means
The iOS Swift `Channel` type decodes a channel definition string of the form `<CHANNEL_PREFIX><id>` (e.g. `__CHANNEL__:<id>`). If the decoded string lacks the prefix separator or has no ID part, `init(from:)` throws a `DecodingError.dataCorrupted` with this message.
Solutions
- Ensure the tauri iOS API Swift package version matches the tauri core version so channel prefixes agree.
- Always pass a real `Channel`/`__CHANNEL__` object from JS/Rust rather than an arbitrary string.
- Check the invoke payload serialization — the channel definition must include both prefix and numeric ID.
- Catch/handle `DecodingError.dataCorrupted` in custom Swift plugin code to log the offending `channelDef`.
Example fix
// before
plugin.call('watch', { onEvent: '__CHANNEL__' }) // missing id
// after
plugin.call('watch', { onEvent: channel }) // real Channel object -> "__CHANNEL__:<id>" Defensive patterns
Strategy: type-guard
Validate before calling
// Swift: validate channel definition shape before decode
func isValidChannelDef(_ s: String, prefix: String) -> Bool {
guard s.hasPrefix(prefix),
let id = s.dropFirst(prefix.count).split(separator: ":").last,
UInt64(id) != nil else { return false }
return true
} Type guard
func asValidChannel(_ s: String) -> Channel? {
isValidChannelDef(s, prefix: CHANNEL_PREFIX) ? nil : nil // use forced decode in do/catch
} Try / catch
// Swift
do {
let channel = try JSONDecoder().decode(Channel.self, from: data)
} catch DecodingError.dataCorrupted(let ctx) {
print("bad channel definition: \(ctx.debugDescription)")
} Prevention
- Keep the tauri iOS Swift package version matched to tauri core
- Pass real Channel objects from JS/Rust, never raw strings
- Log the offending channelDef when decoding fails to spot version drift
When it happens
Trigger: Rust/JS passes a channel identifier string to Swift plugin code that does not match the expected `<prefix><id>` format — empty string, wrong prefix, or only the prefix with no numeric ID.
Common situations: Mismatched tauri core and iOS API (Swift Package) versions where the channel prefix format changed; hand-crafted invoke arguments passing raw strings instead of `Channel` objects; channel serialization dropping the ID.
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)
- missing userInfo for Channel handler. This is a Tauri issue
- unexpected channel value $channelDef
- Arch specified by Xcode was invalid.
- failed to read missing addr file
AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18).
Data as JSON: /api/errors/8c9938260efefdfd.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tauri/mobile/ios-api/Sources/Tauri/Channel.swift:20
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import Foundation
let CHANNEL_PREFIX = "__CHANNEL__:"
let channelDataKey = CodingUserInfoKey(rawValue: "sendChannelData")!
public class Channel: Decodable {
public let id: UInt64
let handler: (UInt64, String) -> Void
public required init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let channelDef = try container.decode(String.self)
let components = channelDef.components(separatedBy: CHANNEL_PREFIX)
if components.count < 2 {
throw DecodingError.dataCorruptedError(
in: container,
debugDescription: "Invalid channel definition from \(channelDef)"
)
}
guard let channelId = UInt64(components[1]) else {
throw DecodingError.dataCorruptedError(
in: container,
debugDescription: "Invalid channel ID from \(channelDef)"
)
}
guard let handler = decoder.userInfo[channelDataKey] as? (UInt64, String) -> Void else {
throw DecodingError.dataCorruptedError(
in: container,
debugDescription: "missing userInfo for Channel handler. This is a Tauri issue"
)
}View on GitHub (pinned to 460ec35447)