Unity-Technologies/UnityCsReference · error · ArgumentNullException

resolver

Error message

resolver

What it means

The RenderPickingResult constructor requires a non-null resolver callback because the picking system must be able to map a picked index back to a concrete handle; a null resolver would cause a NullReferenceException later during picking resolution. Both overloads therefore throw ArgumentNullException(nameof(resolver)).

Source

Thrown at Editor/Mono/Handles/HandleUtility.cs:104

            return renderPickingType == RenderPickingType.RenderFromFilterSet ? contained : !contained;
        }
    }

    public readonly struct RenderPickingResult
    {
        public int renderedPickingIndexCount { get; }
        public HandleUtility.ResolvePickingCallback resolver { get; }
        public HandleUtility.ResolvePickingWithWorldPositionCallback resolverWithWorldPos { get; }

        [NoAutoStaticsCleanup] // default struct value; no mutable state
        public static readonly RenderPickingResult NoOperation = default;

        public RenderPickingResult(int renderedPickingIndexCount, HandleUtility.ResolvePickingCallback resolver)
        {
            if (renderedPickingIndexCount < 0)
                throw new ArgumentOutOfRangeException(nameof(renderedPickingIndexCount), $"The value ({renderedPickingIndexCount}) must not be negative");
            if (resolver == null)
                throw new ArgumentNullException(nameof(resolver));

            this.renderedPickingIndexCount = renderedPickingIndexCount;
            this.resolver = resolver;
            this.resolverWithWorldPos = null;
        }

        public RenderPickingResult(int renderedPickingIndexCount, HandleUtility.ResolvePickingWithWorldPositionCallback resolver)
        {
            if (renderedPickingIndexCount < 0)
                throw new ArgumentOutOfRangeException(nameof(renderedPickingIndexCount), $"The value ({renderedPickingIndexCount}) must not be negative");
            if (resolver == null)
                throw new ArgumentNullException(nameof(resolver));

            this.renderedPickingIndexCount = renderedPickingIndexCount;
            this.resolverWithWorldPos = resolver;
            this.resolver = null;
        }
    }

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Always pass a non-null resolver (a static no-op delegate if picking is intentionally inert).
  2. Use RenderPickingResult.NoOperation when you have no picking to declare, instead of constructing with a null callback.
  3. Initialize resolver delegate fields to a default implementation to avoid accidental nulls.

Example fix

// before
return new RenderPickingResult(count, null);

// after
return count == 0 ? RenderPickingResult.NoOperation : new RenderPickingResult(count, ResolvePicking);
Defensive patterns

Strategy: validation

Validate before calling

if (resolver == null) return RenderPickingResult.NoOperation;
return new RenderPickingResult(count, resolver);

Type guard

static bool HasResolver(HandleUtility.ResolvePickingCallback r) => r != null;

Prevention

When it happens

Trigger: Constructing RenderPickingResult(count, null) for either overload; passing a delegate field that was never assigned; conditional code paths that build the result but forget to supply the callback.

Common situations: Custom handle that returns a picking result without a real resolve handler; refactor that moved the callback into a separate field left null; editor extension wiring up picking incompletely.

Related errors


AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13). Data as JSON: /api/errors/7689eebe7a69a40c. Report an issue: GitHub.