stride3d/stride · error · InvalidOperationException
"videoTexture" was not deallocated properly before trying…
Error message
"videoTexture" was not deallocated properly before trying to create a new one!
What it means
VideoInstance.AllocateVideoTexture throws this InvalidOperationException when a video texture already exists and has not been released. The class enforces a strict allocate/deallocate lifecycle: only one VideoTexture may be live at a time, so re-allocation without an intervening DeallocateVideoTexture is treated as a caller bug rather than being silently tolerated.
Solutions
- Call DeallocateVideoTexture (or the public API that triggers it, e.g. stopping/invalidating the video) before calling AllocateVideoTexture again.
- Ensure the playback lifecycle is linear: allocate -> play -> deallocate -> (optionally) allocate again.
- If reusing the instance, reset it (seek to start / re-prepare via the media player) so its internal texture is released first.
- Wrap the sequence in try/finally so the texture is deallocated even when playback throws.
Example fix
// before videoInstance.AllocateVideoTexture(1920, 1080); videoInstance.Play(); videoInstance.AllocateVideoTexture(1920, 1080); // throws // after videoInstance.AllocateVideoTexture(1920, 1080); videoInstance.Play(); videoInstance.DeallocateVideoTexture(); videoInstance.AllocateVideoTexture(1920, 1080); // ok
Defensive patterns
Strategy: try-catch
Validate before calling
// C# bool canAllocate = videoInstance != null; // texture state is internal; wrap allocation
Try / catch
// C#
try { videoInstance.AllocateVideoTexture(w, h); }
catch (InvalidOperationException ex) when (ex.Message.Contains("not deallocated"))
{
// deallocate and retry once
} Prevention
- Always pair AllocateVideoTexture with DeallocateVideoTexture in try/finally
- Never re-prepare or restart playback on the same VideoInstance without deallocating first
- Do not cache VideoInstance across plays without resetting it
When it happens
Trigger: Calling AllocateVideoTexture(width, height) when the internal videoTexture field is non-null — i.e. after a previous allocation that was not followed by DeallocateVideoTexture, or re-preparing/seeking/restarting the same VideoInstance without releasing its texture.
Common situations: Replaying or restarting a video without disposing the previous playback; calling video preparation APIs twice in a row; a playback path that skips the deallocation step on error or early exit; reusing a cached VideoInstance across plays.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- AVFoundationVideoBackend already initialized.
- mediaCodec has already been initialized
- No resize operation in progress.
- PauseMedia failed: MediaCodecScheduler is null
- PlayMedia failed: MediaCodecScheduler is null
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/f9b6d2f95524744c.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Video/VideoInstance.cs:428
{
if (url == null || startPosition < 0 || length < 0)
return;
var factory = videoSystem.ActiveBackendFactory
?? throw new InvalidOperationException("No video backend is registered or supported on this platform.");
backend = factory.CreateBackend(this);
mediaInitialized = backend.Initialize(url, startPosition, length);
if (!mediaInitialized)
{
backend.Dispose();
backend = null;
}
}
internal void AllocateVideoTexture(int width, int height)
{
if (videoTexture != null)
throw new InvalidOperationException("\"videoTexture\" was not deallocated properly before trying to create a new one!");
videoTexture = new VideoTexture(GraphicsDevice, services, width, height, videoComponent.MaxMipMapCount);
}
private void DeallocateVideoTexture()
{
videoTexture?.Dispose();
videoTexture = null;
}
// Backend-accessible state. Internal to keep VideoInstance's public surface stable.
internal IServiceRegistry Services => services;
internal VideoComponent VideoComponent => videoComponent;
internal VideoTexture VideoTexture => videoTexture;
internal void SetCurrentTime(TimeSpan time) => CurrentTime = time;
internal void SetDuration(TimeSpan duration) => Duration = duration;
// Called by a backend right after it writes a freshly-decoded frame to the target.View on GitHub (pinned to 96fad776d2)