Troubleshoot vision
Fix Vision publishing failures, blank feeds, permission errors, and platform-specific issues in Unity using a structured checklist and decision tree.
Work through this page top to bottom. Most Vision failures fall into one of four categories: connection misconfiguration, frame source failure, platform-specific restrictions, or WebGL origin policy.
Quick checklist
Before diving into specific issues, verify these five things in order:
Confirm a frame source is present
On native platforms (not WebGL), ConvaiVisionPublisher requires a frame source. Confirm CameraVisionFrameSource, WebcamVisionFrameSource, or a custom IVisionFrameSource is on the same GameObject or a child. Check the Console for:
[ConvaiVisionPublisher] No IVisionFrameSource found.Add VisionDebugPreview
Add VisionDebugPreview to any scene GameObject. Press Play. If the overlay shows a live image and FPS > 0, the feed is reaching the publisher. If the overlay is blank or FPS stays at zero, the frame source is not producing frames — continue to Frame source issues below.
Common issues
IsPublishing stays false
Connection Type is Audio
Set Connection Type to Video on ConvaiRoomManager.
Confirm IsPublishing becomes true after switching Connection Type to Video and reconnecting.
IsPublishing stays false
Room not connected
Wait for connection or check API key / network.
Check the Console for [ConvaiRoomManager] connection logs and confirm ConvaiManager.ActiveManager is not null.
IsPublishing stays false
No frame source found
Add CameraVisionFrameSource to the same or child GameObject.
Confirm the Console no longer logs [ConvaiVisionPublisher] No IVisionFrameSource found.
Debug overlay blank, FPS = 0
Frame source in Failed state
Check ErrorKind — see Frame source issues.
Confirm State on the frame source component moves off Failed after applying the matching fix below.
Feed is black
Wrong CameraCaptureMode for render pipeline
See Black feed.
Confirm the VisionDebugPreview overlay shows a non-black image after switching mode.
SrpNative selected
Unimplemented backend
CameraVisionFrameSource enters Failed immediately — use ExplicitRenderCompatibility on SRP/URP.
Confirm State no longer reports Failed with ErrorKind = UnsupportedPlatform.
Webcam not opening
Permission denied (Android / iOS)
Declare android.permission.CAMERA in manifest; add NSCameraUsageDescription in Info.plist.
Confirm State no longer reports PermissionDenied and the webcam preview appears after the permission dialog is granted.
Quest feed not starting
Missing manifest permissions
Declare both horizonos.permission.HEADSET_CAMERA and android.permission.CAMERA.
Confirm passthrough capture starts and State reaches Ready after redeploying with both entries declared.
Quest feed not starting
Wrong hardware
QuestVisionFrameSource requires Quest 3 or 3S. Quest 2 and Quest Pro are not supported.
Confirm the target device is Quest 3 or 3S — State cannot reach Ready on unsupported hardware regardless of permissions.
WebGL feed not publishing
Non-HTTPS origin
Deploy to HTTPS. http://localhost is the only exception.
Confirm the deployed URL uses https:// (or is http://localhost).
WebGL feed not publishing
Frame source assigned
On WebGL the frame source is ignored — remove or leave blank; publisher uses canvas.captureStream().
Confirm IsPublishing becomes true after removing the frame source reference.
Debug overlay blank on WebGL
Expected — no RenderTexture
VisionDebugPreview has no texture to display on WebGL. Verify via IsPublishing instead.
Confirm IsPublishing is true even though the overlay stays blank.
Sampling window has no effect on frame selection
A Sampling Windows entry has Count set but Interval Ms left at 0 (or the reverse)
Set both Count and Interval Ms to nonzero values for every entry under Sampling Windows on ConvaiRoomManager (or the ConvaiRoomManagerProfile asset). Remove entries you are not using instead of leaving one field at 0.
Confirm both fields show nonzero values in the Inspector. A dropped window logs no Console warning — the SDK only warns when window counts exceed the Frames Per Turn budget — so silence does not confirm the window was sent.
Respond mode change has no visible effect
UpdateRespondMode returned false, or the backend rejected the request
Check the bool return value of UpdateRespondMode before assuming it applied; call it only while IsConnected is true. Subscribe to RespondModeUpdateResultReceived and check Status and Message.
Confirm RespondModeUpdateResultReceived.Status is "success" and Modality / Mode match the requested lane and mode. See Vision scripting API for the event subscription pattern.
Frame source issues
Black feed
A black feed (overlay visible but all pixels black) on CameraVisionFrameSource indicates the wrong capture backend for the active render pipeline.
Built-in Render Pipeline
Auto (uses BuiltInHooks)
Camera.onPreRender / Camera.onPostRender hooks work correctly.
URP / SRP
Auto (uses ExplicitRenderCompatibility)
Explicit Camera.Render() in LateUpdate — works on all SRP versions.
URP / SRP with black feed on Auto
ExplicitRenderCompatibility
Forces explicit render path; resolves black feeds on custom SRP configurations.
Do not select SrpNative. It is not implemented in this SDK build. Selecting it causes CameraVisionFrameSource to enter Failed state immediately with ErrorKind = UnsupportedPlatform.
Camera not assigned
If Target Camera is blank and no camera in the scene is tagged MainCamera, CameraVisionFrameSource enters Failed state at startup:
Fix: assign a camera to the Target Camera field, or tag one camera MainCamera.
Webcam permission denied
On Android and iOS, WebcamVisionFrameSource requests camera permission on StartCapture(). If the user denies it:
Android: Verify AndroidManifest.xml declares android.permission.CAMERA.
iOS: Verify Info.plist contains NSCameraUsageDescription with a non-empty string.
If permission was previously denied by the user, the system will not show the dialog again. Direct the user to the device Settings app to re-enable it.
Quest passthrough not starting
QuestVisionFrameSource requires both manifest permissions and the correct hardware.
Required manifest entries:
Without both declarations, passthrough capture fails silently and the frame source enters Failed state. The device does not show a permission dialog — it denies access outright.
Supported hardware: Meta Quest 3 and Quest 3S only. Quest 2 and Quest Pro do not expose PassthroughCameraAccess.
Decision tree
Enable frame health probe
For persistent blank or black frames that do not produce a Failed state, enable the diagnostic probe on CameraVisionFrameSource:
Select the ConvaiVisionRoot GameObject.
On
CameraVisionFrameSource, enable Enable Diagnostic Frame Health Probe.Press Play and watch the Console.
The probe performs a synchronous GPU-to-CPU pixel readback every frame and logs the result. This confirms whether the RenderTexture contains image data or is genuinely blank.
Disable Enable Diagnostic Frame Health Probe before shipping. It performs a synchronous GPU readback every frame, which causes a GPU pipeline stall and significantly reduces frame rate.
Logging
All Vision log messages use LogCategory.Vision. Set the log level to Verbose in Tools → Convai → Configuration → Logging to see all state transitions, frame source discovery, and publishing events.
[ConvaiVisionPublisher]
Publisher lifecycle, frame source discovery, policy changes
[VisionPublishCoordinator]
Track open/close, frame routing
[CameraVisionFrameSource]
Camera capture backend selection, state transitions
[WebcamVisionFrameSource]
Device open, permission request, state transitions
[QuestVisionFrameSource]
Passthrough API binding, state transitions
[VisionDebugPreview]
Frame source discovery, fallback switches
Next steps
If the issue is not covered here, subscribe to VisionCaptureStopped and VideoTrackUnpublished and log the Reason and ErrorMessage fields. See Vision scripting API for the event subscription pattern.
Last updated
Was this helpful?