Troubleshooting
TL;DR: Concrete failure modes, how to spot them, and what to change. Grouped by phase: build-time (Unity / CCK publish), runtime (inside CVR), and logic errors (permissions, serialization, networking).
Build-time
Section titled “Build-time”First CCK build hangs at “Installing…”
Section titled “First CCK build hangs at “Installing…””- Symptom: progress bar stuck on “Installing .NET SDK” or “Installing WASI SDK” for more than a few minutes on the first build.
- Cause:
%LOCALAPPDATA%/ChilloutVR/CVRBuildTools/is populated via direct downloads (dotnet.exe ~200 MB, WASI SDK ~150 MB). - Fix: Let it finish once; subsequent builds are cached. If the download is genuinely stuck, delete the partial
local-dotnet//wasi-sdk/folders and retry —WasmBuildUtility.EnsureDotnetInstalledwill redownload.
error CS0103 inside a WasmBehaviour subclass
Section titled “error CS0103 inside a WasmBehaviour subclass”- Symptom: Unity’s Console shows
The name 'Foo' does not exist in the current contextfor a type that’s clearly imported. - Cause: the WASM publish uses
Microsoft.NET.Sdkwith a shim assembly set, not Unity’s fullUnityEngineDLL. Types outside the shim (e.g.UnityEngine.Input,UnityEngine.Application) fail at the dotnet publish step even if Unity’s in-editor compile accepted them. - Fix: Remove the usage, or replace with a bound alternative. See Not Exposed.
error NETSDK1005: No matching frameworks
Section titled “error NETSDK1005: No matching frameworks”- Symptom: dotnet publish complains about the target framework.
- Cause: the installed dotnet version doesn’t match the version pinned in
WasmBuildUtility.DotnetVersion(10.0.100-preview.5.25277.114as of the current CCK). - Fix: Delete
%LOCALAPPDATA%/ChilloutVR/CVRBuildTools/local-dotnet/and let the build reinstall the exact version.
WasmCompilationException: Failed To Compile Wasm
Section titled “WasmCompilationException: Failed To Compile Wasm”- Symptom: CCK build fails with this exception and one or more
error CS*lines just above. - Cause: your script has compile errors on the WASM side.
- Fix: scroll up in the Unity console to the
error CS*lines; fix them. Common ones:- unbound API (see above)
- unresolved generic method needing reflection under
IlcDisableReflection=true async voidmethods returningTaskout ofUpdate/ event handler scope
ILC complains about reflection
Section titled “ILC complains about reflection”- Symptom:
IL2026/IL3050/IL3002warnings-as-errors about “Using dynamic code”. - Cause: something in your code needs runtime reflection, and the default csproj has
<IlcDisableReflection>true</IlcDisableReflection>. - Fix: pick one:
- Remove the reflection (preferred — the Unity binding surface almost never needs it).
- Set
CCKWasmProjectDescriptor.enableReflection = true. Module size grows significantly.
Runtime — errors visible in the CVR log
Section titled “Runtime — errors visible in the CVR log”WasmAccessDeniedException: Access to member X denied in a Y object context
Section titled “WasmAccessDeniedException: Access to member X denied in a Y object context”- Symptom: exception message mentioning
object context(not scope or owner). - Cause: your script is in the wrong ObjectContext for the API you called. Examples:
- Avatar script calling
LocalPlayer.*orFileStorage.*(both World-only). - Prop script calling
Prop.Destroy()on another prop (allowed World-only).
- Avatar script calling
- Fix: move the functionality to a world script, or use a ObjectContext-appropriate API.
WasmAccessDeniedException: ... in a Y scope context
Section titled “WasmAccessDeniedException: ... in a Y scope context”- Symptom: the message mentions
scope context. - Cause: the target object isn’t in your content root. Writing to a Transform whose GameObject is outside your avatar/prop/world root fails.
- Fix:
- Don’t target external objects; hold references only to children of your own root.
- If you really need to read external state, use getter methods (they are usually
ScopeContext.Any).
WasmAccessDeniedException: ... in a Y owner context
Section titled “WasmAccessDeniedException: ... in a Y owner context”- Symptom: the message mentions
owner context. - Cause: the API requires you to be the content owner (Avatar: worn by you; Prop: spawned by you). Remote clients running the same script hit this.
- Fix: gate the call on a local check — for avatars, compare against
LocalPlayer.PlayerObject == Avatar.GetWearer(). For props, similar withGetSpawner.
The script silently does nothing
Section titled “The script silently does nothing”- Symptom: a method you call appears to have no effect; no exception in the console.
- Causes:
- The host binding is stubbed (
FillNonLinkedWithEmptyStubs) because the import isn’t bound. Look up the symbol inCVR-GameFiles/WasmBinder.Links.*/to confirm. - You defined an event method whose name doesn’t match
UnityEvents/GameEventsenum — the build scanner only dispatches events with exact name matches (e.g.OnWorldPermissionsChanged, notOnPermissionsResult). - The UnityEvent persistent call wasn’t rewired. Check Unity console for
[RerouteUnityEvents]logs after build; ensure your target is aWasmBehavioursubclass.
- The host binding is stubbed (
- Fix: match against the enums in
CVR.CCK.Wasm/Scripting/Enums/and the binder folder lists.
TrapException + VM marked as crashed
Section titled “TrapException + VM marked as crashed”- Symptom: first event runs, subsequent events don’t fire; a TrapException appears once.
- Cause: epoch overrun (a
scripting_call_*took >20 ms) or a WASM trap from the guest (division by zero, OOB memory access, guest exception escape). - Fix:
- Split expensive work across frames.
- Avoid long
forloops over players / world state. - Catch expected exceptions inside your handlers so they don’t escape to the host.
OnWorldPermissionsChanged never fires
Section titled “OnWorldPermissionsChanged never fires”- Symptom: user toggles a permission in the CVR UI; your script doesn’t react.
- Causes:
- Method name doesn’t match the enum exactly. Must be
void OnWorldPermissionsChanged(). - Method is static, private-but-with-attribute-required-to-detect, or has parameters. The scanner uses
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublicso private is fine; but it expects zero parameters for this event.
- Method name doesn’t match the enum exactly. Must be
- Fix: confirm the signature:
void OnWorldPermissionsChanged().
Runtime — silent behaviour changes after rebuild
Section titled “Runtime — silent behaviour changes after rebuild”Public field reset after rebuild
Section titled “Public field reset after rebuild”- Symptom: a value you set in the Unity inspector reverts to the default after a CCK build.
- Cause: the field is
publicbut of an unsupported type, or the containing class lacks[WasmSerialized]. - Fix: either use a supported type (see Serialization) or add
[WasmSerialized]to the class (if it’s a custom type).
Private field resets on every load
Section titled “Private field resets on every load”- Symptom: a private counter / cache that should persist across script reloads starts at 0 again.
- Cause: private fields are not serialized by default.
- Fix: add
[WasmSerialized]to the field.
Public field unexpectedly persists
Section titled “Public field unexpectedly persists”- Symptom: a UI-state or debug counter refuses to reset.
- Cause: public fields serialize by default.
- Fix: add
[NonWasmSerialized]to the field.
Networking
Section titled “Networking”CVR_Networking_SendMessage silently fails
Section titled “CVR_Networking_SendMessage silently fails”- Symptom: you
Networking.SendMessage(...)but no remote client receives it. - Causes:
- Payload exceeds MTU. Run
Networking.WillMessageBeDropped(size)before sending. - Network is saturated. Check
Networking.NetworkCloggedPercentage()— back off if > 0.7. playerIdsarray references players who’ve left the instance.
- Payload exceeds MTU. Run
- Fix: split the payload, switch to
SendType.Reliablefor large messages, or drop-and-retry with latest player list.
Handlers fire on the wrong client
Section titled “Handlers fire on the wrong client”- Symptom: what you meant as “only the instance owner authorizes” runs on every client.
- Cause: every client runs the same script. Only you, in code, decide who is authoritative.
- Fix: early-return in the handler unless
Networking.GetInstanceOwner() == LocalPlayer.PlayerObject.
File storage
Section titled “File storage”FileStorage_* calls throw
Section titled “FileStorage_* calls throw”- Cause: either the script isn’t in World context, or
WorldPermissions.CurrentPermissions.FileStorageApiAllowed == false. - Fix:
- If avatar/prop script: move file storage to a world script, or network a “save this” message to the world instance owner.
- If world script: call
WorldPermissions.Request(...)once inStartand gateFileStoragecalls onCurrentPermissions.FileStorageApiAllowed.
Quota exceeded
Section titled “Quota exceeded”- Symptom: writes fail once the world has accumulated near its quota.
- Cause: total bytes in
WorldData/{worldId}/*>FileStorageStorageLimit. - Fix: delete files before writing, or request a higher quota by resending
WorldPermissions.Requestwith a largerFileStorageStorageLimit.
UnityEvent rewiring
Section titled “UnityEvent rewiring”Persistent call doesn’t reach the script
Section titled “Persistent call doesn’t reach the script”- Symptom: the Unity button fires but the method doesn’t run inside WASM.
- Causes:
- The persistent call target is still the
WasmBehaviourtype instead of the runtime replacement. Check the inspector after build — target should sayWasmRuntimeBehaviour. - The method isn’t
publicon the script. The rewrite code path assumes public methods. - The method has multiple parameters. Only single-argument (or void) methods are rewireable.
- The persistent call target is still the
- Fix:
- Rebuild via the CCK to re-run rewiring.
- Make the method public.
- Pack multi-arg calls into a struct passed through a single string/bytes argument.
Asking for help
Section titled “Asking for help”When reporting an issue, include:
- CCK version + Unity version.
- The
CCKWasmProjectDescriptortoggles you used. - The exact error line from the Unity console (for build issues) or the CVR log (for runtime issues).
- A minimal repro script (ideally diffed against one of the Examples).
Related
Section titled “Related”- Permissions — the three-axis model.
- World Permissions — the request/approve flow.
- Unity Events Rewiring — persistent call mechanics.