Develop

Known issues

Updated: Apr 2, 2026

Layers displaying incorrect cropping

When multiple SceneQuadLayer instances share the same SceneSwapchain and each calls setClip() with different UV clip regions, all layers display the same clip instead of their individually specified clip regions.

Expected behavior

Each layer should display its own unique UV clip region from the shared swapchain texture. For example, when rendering a cubemap with six layers sharing one swapchain, each layer should show a different face of the cube based on its individual clip settings.

Actual behavior

All layers display the same UV clip region, typically showing the last clip region that was set across all layers. This means:
  • Layer-specific clip regions are ignored
  • Only the most recently applied clip settings take effect globally
  • Multiple layers appear identical instead of showing different portions of the texture

Workaround

Consider using Meta Spatial SDK version 0.7.2 if this functionality is critical to your application.

Layer incorrectly created when using mesh-based rendering

When using ReadableMediaPanelRenderOptions with renderMode = PanelRenderMode.Mesh(), the system incorrectly creates a compositor layer instead of using only mesh-based rendering.

Expected behavior

When PanelRenderMode.Mesh() is specified, the panel should render using only a 3D mesh without creating a compositor layer.

Actual behavior

The system creates both a mesh and a compositor layer, which:
  • Consumes additional GPU memory and processing resources
  • May impact rendering performance
  • Goes against the intended lightweight mesh-only rendering approach

Workaround

If you’re creating ReadableMediaPanelSettings objects, you can work around the issue by applying the fix after converting to panel configuration:
val panelSettings = ReadableMediaPanelSettings(
    shape = QuadShapeOptions(width = 1.0f, height = 1.0f),
    display = PixelDisplayOptions(width = 1920, height = 1080),
    rendering = ReadableMediaPanelRenderOptions(
        renderMode = PanelRenderMode.Mesh(),
        // ... other render options
    ),
    // ... other settings
)

val panelConfig = panelSettings.toPanelConfigOptions()
panelConfig.layerConfig = null  // Override the incorrect layer creation

// Use panelConfig for your panel setup

Degraded performance in debug mode

Spatial SDK applications experience significantly reduced performance when built and run in debug mode compared to release builds.

Expected behavior

Applications should perform at similar levels across build types. Debug builds should run close to release builds for basic testing.

Actual behavior

Debug builds exhibit notably degraded performance.

Workaround

Switch to release build variant for performance-sensitive testing:
  1. In Android Studio, open the Build Variants tool window by navigating to View > Tool Windows > Build Variants
  2. In the Build Variants window, locate your app module in the list
  3. Change the build variant from debug (default) to release for the app you are testing
Note: Remember to switch back to debug mode when needed. Consider using release builds for performance profiling and user experience validation.

Audio interrupted when entering immersive mode

When an immersive application requests audio focus, background audio from other apps (such as YouTube or music players) may stop or become altered. This is caused by Android’s audio focus policies, which were designed for phone-centric use cases and do not fully account for the multi-app XR environment on Horizon OS.

Expected behavior

Background audio from non-immersive apps should continue playing uninterrupted when an immersive app is launched, as long as the immersive app does not explicitly need exclusive audio output.

Actual behavior

Entering an immersive experience can cause one or more of the following:
  • Background audio from other apps stops completely
  • Audio spatialization changes unexpectedly (for example, losing spatial positioning)
  • Audio does not resume after exiting the immersive experience

Workaround

There is currently no SDK-level fix for this issue. To mitigate the impact in your app:
  • Avoid requesting AUDIOFOCUS_GAIN unless your app absolutely requires exclusive audio. Use AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK if your app only needs temporary audio focus and can allow other audio to duck (play at reduced volume).
  • If your app plays background audio, handle AudioManager.OnAudioFocusChangeListener to gracefully pause and resume playback when focus is lost and regained.
  • Test audio behavior with other apps running in the background to verify that your app does not unintentionally disrupt their audio.

2D panel not reappearing after finishing an immersive activity

When transitioning from an immersive activity back to a 2D panel, calling finish() on the immersive activity may cause the 2D panel to not reappear. In some cases, calling finish() on an activity with panels that have enableLayer = true can cause a crash (SIGSEGV) inside libMetaSpatialSDK.so.
Note: The enableLayer parameter is deprecated. Use layerConfig: LayerConfig? instead to configure panel layer behavior.

Expected behavior

After an immersive activity completes, the previous 2D panel activity should reappear and be interactive.

Actual behavior

  • The 2D panel does not reappear after the immersive activity finishes.
  • If the activity has panels with enableLayer = true (deprecated; use layerConfig instead), calling finish() may cause a native crash due to improperly destroyed mesh, layer, and texture resources.

Workaround

Do not use finish() to close an activity that has associated panels. Instead:
  • Use panelEntity.destroy() to properly clean up panel resources before ending the activity. See Safely destroying activity-based panels for more details.
  • Use a helper function to launch panel mode in home instead of calling finish() to transition from immersive mode back to 2D panel mode. This avoids both the crash and the missing panel issue.
// Don't do this — may crash or leave panels in a broken state
// finish()

// Do this instead — transitions back to panel mode safely
launchPanelModeInHome()
The launchPanelModeInHome() function is not an SDK method, it’s a helper pattern you implement in your app using Android intents. For a complete working example, see the HybridSample app in the Meta Spatial SDK Samples repository.

Hand UI becoming unresponsive

Hand-based UI interactions may become unresponsive in certain scenarios, particularly when using dynamically created panels or when switching between input modalities (hands and controllers).

Expected behavior

Hand interactions with UI panels should remain responsive throughout the session, including when panels are created dynamically and when switching between hand tracking and controller input.

Actual behavior

  • Dynamically created panels using ComposeViewPanelSettings may lose touch input responsiveness.
  • Scrollable views may not respond to direct hand interaction (physical touch), though distance pointer interaction may still work.
  • Switching between controllers and hand tracking may occasionally trigger unintended input events on UI elements.

Workaround

  • If you are using dynamically created panels with ComposeViewPanelSettings, update to Meta Spatial SDK v0.9.1 or later, which includes fixes for panel input corruption.
  • If scrollable views do not respond to direct hand touch, use distance pointer interaction (pointing from a distance and pinching) as a fallback until a fix is available.
  • For wrist-attached controls, refer to the Meta Spatial Scanner showcase app for a working implementation pattern.