-
-
Notifications
You must be signed in to change notification settings - Fork 55
Troubleshooting
Symptoms, and what actually causes them. Most entries here are failures that do not name their own cause — that is why they are worth writing down.
Start with Platform prerequisites if you have not read it; three of the entries below are simply that page not having been read.
The Windows App Runtime is missing. No exception, no log line, no message. Your app stops before
Main.
A missing library would have thrown by name. This blocks instead, inside a bootstrapper injected into the module constructor of anything referencing the package. It is the hardest failure on this page to recognise, and the easiest to fix:
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>Full explanation, including who has the runtime and who does not, in Platform prerequisites.
Confirm it before you believe it: attach a debugger and break in. The stack will show
Bootstrap.TryInitialize under <Module>..cctor().
The interop script tag is missing, or it is placed after blazor.webassembly.js.
<script src="_content/WebRTCme/JsInterop.js"></script>If you are upgrading from 2.0.0, the path changed — it used to be
_content/WebRTCme.Bindings.Blazor/JsInterop.js, and that package no longer exists.
Same cause as above.
Expected, and yours to fix — the error does not mention WebRTCme but it is about it. Pin the versions the packages want:
<PackageReference Include="Microsoft.Maui.Controls" Version="10.0.101" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="10.0.101" />The same error appears in the opposite direction if you upgrade WebRTCme and leave an old pin behind. Releases states the version each release wants.
You are trying to build a test or console project for Mac Catalyst. Catalyst builds an .app, not
an executable, and there is no app host to be had — setting UseAppHost=true produces exactly this.
The two requirements cannot both be satisfied; a Catalyst executable has to be an app. See
Testing, tier 4.
You asked a multi-targeted project to build on a Mac and it defaulted to a Windows target framework.
Confusing when you asked for Catalyst. Note that passing -f or -p:TargetFramework does not
fix it: the build honours them and the implicit restore does not, so you then get NETSDK1005
saying the assets file has no target for the framework you just supplied. The project has to pick
its own framework.
You are on a fallback slice. NuGet falls back: a net10.0-android project restoring a package
with no Android slice resolves lib/net10.0/ instead and compiles perfectly, because the API is
identical across slices. There is simply no binding behind it.
Check obj/project.assets.json for your target framework and confirm it resolved its own slice
rather than net10.0. This is exactly what Tests/Test-Package.ps1 asserts — see
Testing.
You are using project references rather than packages, and the binding's .resources.zip did
not reach your app. That zip is what the Apple SDK extracts WebRTC.xcframework from; the bindings
are referenced with PrivateAssets="all", which stops it flowing.
Reference the platform binding project directly, as WebRTCme.DemoApp.Maui does. Package
consumers do not need this and should not do it — in a package the binding and its zip sit side by
side in lib/<tfm>/, which the SDK already understands. See Demo apps.
The framework must be a versioned bundle — Versions/A plus symlinks. Git on Windows cannot
check those symlinks out without core.symlinks, so the binary arrives as a 23-byte text file
holding a path. Every package built on Windows before this release carried exactly that.
If you are building from source on Windows, build-versioned-framework.sh reassembles it. If you
are consuming a package, take 26.9.16 or later.
The native payload is not beside your app. On Windows that is WebRtcInterop.dll plus its import
closure — abseil, BoringSSL, protobuf, libc++ — and the MSVC runtime. They ship at
runtimes/win-x64/native/ and should be copied by the SDK.
If you refreshed the native binaries by hand, check you took the whole closure and not just
WebRtcInterop.dll.
That part of the W3C surface is not implemented on that platform. What works where lists what is missing and, more usefully, explains that the count is not the measure — most of it has never been reached by anything.
If you hit one on a path that matters to you, please open an issue. That is the signal that decides what gets filled in next: it means something moved from "nothing calls it" to "something does".
Recording (MediaRecorder) is the most likely one to meet: it is Blazor only.
Fixed in 26.9.15. CreateDataChannel(label) with no options threw on Android, iOS and Mac Catalyst.
Upgrade.
Fixed in 26.9.15. Before that, every Blazor consumer had to reach into JSRuntime's non-public
JsonSerializerOptions by reflection.
If you see this on 26.9.15 or later, it is a regression — please report it. Do not reinstate the reflection workaround; the fix belongs in the binding.
Separate "arriving" from "drawn". IConnection.GetStats(peerId) tells you whether frames are
actually being received; if bytes are climbing and the tile is blank, it is a rendering problem
rather than a media one.
On MAUI, check the Media handler is registered:
handlers.AddHandler(typeof(Media), typeof(MediaHandler));Known and open. Rotating the device does not rotate the picture locally. The demo apps lock to portrait, which mitigates rather than fixes it.
ILogger calls in the middleware go nowhere on every MAUI platform unless a provider is registered.
The MAUI demo does this:
builder.Logging.AddProvider(new ConsoleLoggerProvider());You need TURN. STUN alone lets a peer discover its public address, which is enough when at least one NAT cooperates. When both peers are behind symmetric NAT — common on mobile networks and corporate wifi — neither can reach the other and the call needs a relay.
The signalling server ships with StunOnlyProxy registered and TURN proxies for Xirsys, Twilio and
coturn present but commented out. See
Connection: Signaling.
Its configured server address points at 192.168.1.48, which is a machine on the author's LAN and
not yours. Both demos need a server you deploy, and their appsettings.json edited. See
Demo apps.
The Blazor demo shows a signalling server down banner for this case.
Peer id is the display name. Give each device a different name.
A client killed abruptly — swiped away rather than leaving the page — sends no close frame, so the server keeps the peer until its own keepalive notices, which takes minutes. To test peers leaving, leave the call page instead of killing the app.
DOMAIN must match the host in the clients' BaseUrl. The server compares the HTTP Origin
against its own by scheme and host, and a missing Origin counts as a mismatch. A browser
served from localhost and a phone reaching 192.168.1.48 cannot both be accepted at once.
Note that a 403 on https://<host>:4443/rooms/test is the healthy answer for a plain curl —
the API is access controlled, so 403 means TLS terminated and the server replied.
Publish every RTC port you created. The server makes one worker per CPU by default and gives
each its own port from 44444 upwards, so 32 cores means 44444–44475. NUM_WORKERS is not a
performance knob here — it decides how many ports you need. Use NUM_WORKERS=1 for testing.
Also check MEDIASOUP_ANNOUNCED_ADDRESS is an address every client can reach.
Turn simulcast off. Measured over one LAN: 64–159 kbit/s at 289x240 with simulcast, against
1781–1828 kbit/s at 578x480 without. It is mediasoup's congestion control rather than this client.
The demo apps ship with UseSimulcast: false for this reason. See
Connection: MediaSoup.
On Android, simulcast does not encode at all with this libwebrtc build.
Fixed. If you see it, you are on an old build — upgrade.
-
doc/KnownGaps.mdin the repository is the long-form engineering record. Entries are kept after they are fixed, with what the fault looked like beforehand — which is often the fastest way to recognise something. - Open an issue with your platform, the package version, and the exception or the absence of one. "It hangs with no error" is a useful report here; several things on this page fail exactly that way.
Start here
The stack
- WebRTCnative
- Bindings
- The unified API
- Middleware
- Connection
- · Signaling (mesh)
- · MediaSoup (SFU)
- Demo apps
Reference
When it breaks