stride3d/stride · error · ArgumentException

The object must be IDisposable, IReferenceable, or IntPtr

Error message

The object must be IDisposable, IReferenceable, or IntPtr

What it means

ObjectCollector.Add<T> only accepts objects that are IDisposable, implement IReferencable, or are an IntPtr memory handle, because it must know how to release them during disposal. Passing any other object type is rejected with this ArgumentException to keep the collector's cleanup contract sound.

Solutions

  1. Make the registered type implement IDisposable and put its cleanup in Dispose().
  2. If it wraps native memory, register the IntPtr handle allocated via MemoryUtilities.Allocate instead.
  3. If it is a reference-counted Stride object, implement/inherit IReferencable.
  4. If the object needs no cleanup, do not register it in the collector.

Example fix

// before
collector.Add(new ConfigSnapshot()); // not IDisposable
// after
class ConfigSnapshot : IDisposable { public void Dispose() { ... } }
collector.Add(new ConfigSnapshot());
Defensive patterns

Strategy: type-guard

Validate before calling

if (obj is not IDisposable and not IReferencable and not IntPtr)
    throw new InvalidOperationException("Object is not registrable in ObjectCollector");

Type guard

static bool IsCollectible<T>(T o) where T : notnull => o is IDisposable or IReferencable or IntPtr;

Try / catch

try { collector.Add(obj); }
catch (ArgumentException ex) when (ex.ParamName == "objectToDispose")
{
    // object type not managed by the collector; handle or register a wrapper
}

Prevention

When it happens

Trigger: Calling collector.Add(someObject) where someObject's runtime type implements none of IDisposable, IReferencable, and is not an IntPtr.

Common situations: Registering plain POCOs or service objects in a ComponentBase/Dispose collector by mistake; refactors that drop IDisposable from a registered class; wrapping a resource in a non-disposable adapter.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at sources/core/Stride.Core/ObjectCollector.cs:62

    {
        disposables ??= [];
    }

    /// <summary>
    ///   Adds an object implementing the <see cref="IDisposable"/> or <see cref="IReferencable"/> interfaces,
    ///   or a <see cref="IntPtr"/> to an object allocated using <see cref="MemoryUtilities.Allocate"/>
    ///   to the list of the objects to dispose.
    /// </summary>
    /// <typeparam name="T">The type of the object to add.</typeparam>
    /// <param name="objectToDispose">The object to add to the collector to be disposed at a later time.</param>
    /// <exception cref="ArgumentException">
    ///   <paramref name="objectToDispose"/> does not implement the interface <see cref="IDisposable"/>, <see cref="IReferencable"/>,
    ///   and is not a valid memory pointer allocated by <see cref="MemoryUtilities.Allocate"/>.
    /// </exception>
    public T Add<T>(T objectToDispose) where T : notnull
    {
        if (objectToDispose is not (IDisposable or IReferencable or IntPtr))
            throw new ArgumentException("The object must be IDisposable, IReferenceable, or IntPtr", nameof(objectToDispose));

        // Check memory alignment
        if (objectToDispose is IntPtr memoryPtr && !MemoryUtilities.IsAligned(memoryPtr))
            throw new ArgumentException("The memory pointer is invalid. Memory must have been allocated with MemoryUtilities.Allocate", nameof(objectToDispose));

        EnsureValid();

        if (!disposables.Contains(objectToDispose))
            disposables.Add(objectToDispose);

        return objectToDispose;
    }

    /// <summary>
    ///   Removes a disposable object from the list of the objects to dispose.
    /// </summary>
    /// <typeparam name="T">The type of the object to remove.</typeparam>
    /// <param name="objectToDispose">The object to be removed from the list of objects to dispose.</param>

View on GitHub (pinned to 96fad776d2)