stride3d/stride · error · InvalidOperationException

Error when serializing reference.

Error message

Error when serializing reference.

What it means

In ArchiveMode.Serialize, ReferenceSerializer writes the object's attached reference (Id + Url). If the object has no attached reference or its Url is null, there is no location to write, so the library throws instead of emitting an unresolvable reference.

Solutions

  1. Ensure the object was created/loaded through the ContentManager so it has an attached reference with a Url
  2. Attach reference metadata manually via AttachedReferenceManager before serializing
  3. Skip/guard serialization paths that only need hashes by giving the object a valid Url

Example fix

// before
var tex = new Texture();
contentManager.Save("out", wrapper); // throws: no attached reference
// after
var tex = contentManager.Load<Texture>("my-texture"); // has attached reference
contentManager.Save("out", wrapper);
Defensive patterns

Strategy: validation

Validate before calling

var ar = AttachedReferenceManager.GetAttachedReference(obj);
if (ar?.Url == null) throw new InvalidOperationException($"{obj.GetType().Name} has no attached content reference; load it via ContentManager");

Type guard

static bool IsSerializableReference(object o) => AttachedReferenceManager.GetAttachedReference(o)?.Url != null;

Try / catch

try { SerializeRef(stream, obj); }
catch (InvalidOperationException ex) when (ex.Message == "Error when serializing reference.") { // object lacks attached reference
}

Prevention

When it happens

Trigger: Serializing an object that is an IReferencable without attached reference metadata (not created/tracked by the content system), e.g. during build engine command hash computation when the object was constructed in memory rather than loaded.

Common situations: Manually instantiating an asset class with 'new' and saving it; passing a runtime-created object into a serialization path that expects content-managed objects; objects whose AttachedReference was stripped.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at sources/core/Stride.Core.Serialization/Serialization/Contents/ReferenceSerializer.cs:88

                    }
                }
            }
        }
        else if (referenceSerialization == ContentSerializerContext.AttachedReferenceSerialization.AsNull)
        {
            if (mode == ArchiveMode.Deserialize)
            {
                obj = default;
            }
        }
        else if (referenceSerialization == ContentSerializerContext.AttachedReferenceSerialization.AsSerializableVersion)
        {
            if (mode == ArchiveMode.Serialize)
            {
                // This case will happen when serializing build engine command hashes: we still want Location to still be written
                var attachedReference = AttachedReferenceManager.GetAttachedReference(obj);
                if (attachedReference?.Url == null)
                    throw new InvalidOperationException("Error when serializing reference.");

                // TODO: Do not use string
                stream.Write(obj.GetType().AssemblyQualifiedName);
                stream.Write(attachedReference.Id);
                stream.Write(attachedReference.Url);
            }
            else
            {
                var type = AssemblyRegistry.GetType(stream.ReadString());
                var id = stream.Read<AssetId>();
                var url = stream.ReadString();

                obj = (T)AttachedReferenceManager.CreateProxyObject(type, id, url);
            }
        }
        else if (referenceSerialization == ContentSerializerContext.AttachedReferenceSerialization.Clone)
        {
            var cloneReferences = stream.Context.Get(ReferenceSerializer.CloneReferences);

View on GitHub (pinned to 96fad776d2)