stride3d/stride · error · OptionException

Expect name1=value1;name2=value2 format.

Error message

Expect name1=value1;name2=value2 format.

What it means

IInitializingObjectNode.AddMember may only run while the node graph is being constructed; once the GraphNode is sealed, its member set is immutable, and adding another child throws InvalidOperationException. Sealing is the mechanism that freezes the node structure after initialization.

Solutions

  1. Add all members during node initialization, before the node is sealed.
  2. Rebuild/re-create the node (or its containing model) if members must change.
  3. Check IsSealed before calling AddMember and skip or defer dynamic members.

Example fix

// before
((IInitializingObjectNode)objectNode).AddMember(memberNode, false);
// after
if (!objectNode.IsSealed)
    ((IInitializingObjectNode)objectNode).AddMember(memberNode, false);
Defensive patterns

Strategy: validation

Validate before calling

if (objectNode.IsSealed)
    throw new InvalidOperationException("Node already sealed; rebuild it to add members");

Type guard

bool AcceptsMembers(ObjectNode node) => !node.IsSealed;

Try / catch

try { ((IInitializingObjectNode)node).AddMember(member, false); }
catch (InvalidOperationException ex) when (ex.Message.Contains("sealed")) { /* defer or rebuild the node */ }

Prevention

When it happens

Trigger: Calling AddMember on an ObjectNode after construction/sealing completed — e.g. attempting to attach a late-discovered member or a dynamic child to an already-built node.

Common situations: Dynamically adding properties to objects at runtime after their node was built; duplicate type description changes or re-initialization attempts on live nodes.

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


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/ab34a8490ded274d. Report an issue: GitHub.

Appendix: source

Thrown at sources/assets/Stride.AssetCompiler/PackageBuilderApp.cs:148

                { "slave=", "Slave pipe", v => options.SlavePipe = v }, // Benlitz: I don't think this should be documented
                { "crash-dir=", "Slave only: shared crash run directory the master collects crashes from", v => options.CrashRunDirectory = v },
                { "dump-dir=", "crash-adopt only: directory of createdump minidumps to adopt into the crash store", v => options.NativeDumpDirectory = v },
                { "server=", "This Compiler is launched as a server", v => { } },
                { "graphics-api=", "Graphics API to load (Direct3D11|Direct3D12|Vulkan). Applied at startup by GraphicsApiSelector.", v => { } },
                { "pack-asset-assembly=", "Host-loadable asset assembly (package-relative path) to declare in the packed sdpkg; repeat for each", v => options.PackAssetAssemblies.Add(v) },
                { "pack-asset-namespace=", "Asset URL namespace declaration to resolve into the packed sdpkg (true/false/name)", v => options.PackAssetNamespace = v },
                { "t|threads=", "Number of threads to create. Default value is the number of hardware threads available.", v => options.ThreadCount = int.Parse(v) },
                { "test=", "Run a test session.", v => options.TestName = v },
                { "no-backup", "Upgrade verb only: skip backing up the files the upgrade overwrites (backup is on by default).", v => options.NoBackup = v != null },
                { "property:", "Properties. Format is name1=value1;name2=value2", v =>
                {
                    if (!string.IsNullOrEmpty(v))
                    {
                        foreach (var nameValue in v.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            var equalIndex = nameValue.IndexOf('=');
                            if (equalIndex == -1)
                                throw new OptionException("Expect name1=value1;name2=value2 format.", "property");

                            var name = nameValue.Substring(0, equalIndex);
                            var value = nameValue.Substring(equalIndex + 1);
                            if (value != string.Empty)
                                options.Properties.Add(name, value);
                        }
                    }
                }
                },
                { "compile-property:", "Compile properties. Format is name1=value1;name2=value2", v =>
                {
                    if (!string.IsNullOrEmpty(v))
                    {
                        if (options.ExtraCompileProperties == null)
                            options.ExtraCompileProperties = new Dictionary<string, string>();

                        foreach (var nameValue in v.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                        {

View on GitHub (pinned to 96fad776d2)