stride3d/stride · error · InvalidOperationException
Cannot register new platforms. RegisterSupportedPlatforms…
Error message
Cannot register new platforms. RegisterSupportedPlatforms can only be called once
What it means
AssetRegistry.RegisterSupportedPlatforms throws InvalidOperationException if SupportedPlatforms has already been populated. Platform support is a process-wide, write-once static configuration: mixing registration calls would produce ambiguous platform sets.
Solutions
- Guard the call: only register when AssetRegistry.SupportedPlatforms.Count == 0.
- Move registration to a single central bootstrap point and have other modules read the existing value.
- In tests, register once in a one-time setup (or check the guard before each registration).
Example fix
// before
AssetRegistry.RegisterSupportedPlatforms(platforms);
// after
if (AssetRegistry.SupportedPlatforms.Count == 0)
AssetRegistry.RegisterSupportedPlatforms(platforms); Defensive patterns
Strategy: validation
Validate before calling
if (AssetRegistry.SupportedPlatforms.Count > 0) return; // already registered AssetRegistry.RegisterSupportedPlatforms(platforms);
Try / catch
try { AssetRegistry.RegisterSupportedPlatforms(platforms); } catch (InvalidOperationException) { /* already registered - ignore */ } Prevention
- Register platforms exactly once in a single bootstrap method.
- Use a Lazy<T>/Singleton for asset-system initialization.
- In tests, register in [OneTimeSetUp]/static setup, not per-test.
When it happens
Trigger: Calling AssetRegistry.RegisterSupportedPlatforms a second time in the same process, e.g. from both a plugin and the host app, or in a repeated test setup without clearing state.
Common situations: Two modules each initializing the asset system at startup; unit tests re-registering platforms per fixture because static state persists between tests.
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
- Unable to find the base
- Unable to find the graph corresponding to the base part
- The base is unset for the current node.
- No Collection item identifier associated to the given…
- An item has been added to a collection that does not have a…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/3cdfcb940c9e7636.
Report an issue: GitHub.
Appendix: source
Thrown at sources/assets/Stride.Core.Assets/AssetRegistry.cs:76
/// </summary>
/// <value>The supported platforms.</value>
public static SolutionPlatformCollection SupportedPlatforms { get; }
/// <summary>
/// Gets an enumeration of registered importers.
/// </summary>
/// <value>The registered importers.</value>
public static IEnumerable<IAssetImporter> RegisteredImporters { get { lock (RegistryLock) { return RegisteredImportersInternal; } } }
/// <summary>
/// Registers the supported platforms.
/// </summary>
/// <param name="platforms">The platforms.</param>
/// <exception cref="System.ArgumentNullException">platforms</exception>
public static void RegisterSupportedPlatforms(List<SolutionPlatform> platforms)
{
ArgumentNullException.ThrowIfNull(platforms);
if (SupportedPlatforms.Count > 0) throw new InvalidOperationException("Cannot register new platforms. RegisterSupportedPlatforms can only be called once");
SupportedPlatforms.AddRange(platforms);
}
/// <summary>
/// Determines whether the file is an asset file type.
/// </summary>
/// <param name="extension">The file.</param>
/// <returns><c>true</c> if [is asset file file] [the specified file]; otherwise, <c>false</c>.</returns>
public static bool IsAssetFileExtension(string? extension)
{
if (extension == null) return false;
lock (RegistryLock)
{
return RegisteredAssetFileExtensions.ContainsKey(extension);
}
}
/// <summary>View on GitHub (pinned to 96fad776d2)