stride3d/stride · error · ArgumentException

Unable to retrieve value for

Error message

Unable to retrieve value for [{0}]

What it means

PropertyContainer.GetSafe<T> is the strict variant of Get: for reference-type property keys it demands that a value exists and throws ArgumentException (with the key formatted into the message) when Get returns null. Use it only when absence of the property is a bug; the non-safe Get returns the default instead.

Solutions

  1. Check the property is set (Get(key) != null or ContainsKey) before calling GetSafe.
  2. Use non-throwing Get(key) and handle the default value instead.
  3. Assign the property (or give the PropertyKey a default value metadata) before reading.
  4. Verify you are querying the same PropertyKey instance and owner type used when setting.

Example fix

// before
var name = properties.GetSafe(MyKeys.NameProperty); // throws if unset
// after
if (properties.TryGetValue(MyKeys.NameProperty, out var name2)) { ... }
// or
var name3 = properties.Get(MyKeys.NameProperty); // returns default
Defensive patterns

Strategy: try-catch

Validate before calling

if (properties.Get(myKey) is null)
    throw new InvalidOperationException($"Property {myKey.Name} not set before GetSafe");

Type guard

static bool HasValue<T>(PropertyContainer c, PropertyKey<T> k) where T : class => c.Get(k) != null;

Try / catch

try { var v = properties.GetSafe(key); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Unable to retrieve value for"))
{
    // property was never set; fall back to default or initialize it
}

Prevention

When it happens

Trigger: Calling container.GetSafe(key) for a PropertyKey that was never set on that object (and has no default value producing a stored result) — Get(propertyKey, false) yields null and the exception is thrown.

Common situations: Reading an attached property before any code assigned it; key registered on a different owner type than expected; assuming a default exists when the key's default metadata is null; deserialized objects missing the property.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at sources/core/Stride.Core/PropertyContainer.cs:293

    }

    /// <summary>
    /// Gets the value of a property key or throw an error if the value was not found
    /// </summary>
    /// <typeparam name="T">Type of the property key</typeparam>
    /// <param name="propertyKey">The property key.</param>
    /// <returns>The value associated with this property key.</returns>
    /// <exception cref="ArgumentNullException">propertyKey</exception>
    /// <exception cref="ArgumentException">Unable to retrieve value for [{0}].ToFormat(propertyKey)</exception>
    public T GetSafe<T>(PropertyKey<T> propertyKey)
    {
        ArgumentNullException.ThrowIfNull(propertyKey);
        if (propertyKey.IsValueType)
        {
            return Get(propertyKey);
        }

        var result = Get(propertyKey, false) ?? throw new ArgumentException("Unable to retrieve value for [{0}]".ToFormat(propertyKey));
        return (T)result;
    }

    /// <summary>
    /// Gets the specified tag value.
    /// </summary>
    /// <typeparam name="T">Type of the tag value</typeparam>
    /// <param name="propertyKey">The tag property.</param>
    /// <returns>Typed value of the tag property</returns>
    public T? Get<T>(PropertyKey<T> propertyKey)
    {
        ArgumentNullException.ThrowIfNull(propertyKey);
        if (propertyKey.IsValueType)
        {
            // Fast path for value type
            // First, check if there is an accessor
            if (propertyKey.AccessorMetadata != null)
            {

View on GitHub (pinned to 96fad776d2)