stride3d/stride · error · ArgumentException
The type doesn't have an assembly-qualified name
Error message
The type doesn't have an assembly-qualified name
What it means
DynamicTypeAttributeBase stores a Type as TypeName using Type.AssemblyQualifiedName so editors/serializers can later resolve and instantiate it dynamically. For some types — notably open generic type parameters (the T itself) and certain dynamic or trimmed types — AssemblyQualifiedName returns null. Since the type could never be resolved by name later, the constructor throws ArgumentException immediately.
Solutions
- Pass a closed, concrete Type (e.g. typeof(MyConcreteType)) instead of a generic type parameter.
- Move the attribute application to a non-generic context where the concrete type is known.
- Check type.AssemblyQualifiedName != null before constructing and fall back to the typeName string constructor with a valid name.
Example fix
// before var attr = new MyDynamicTypeAttribute(typeof(T)); // throws: T has no assembly-qualified name // after var attr = new MyDynamicTypeAttribute(typeof(ConcreteHandler)); // closed type with a valid AQN
Defensive patterns
Strategy: type-guard
Validate before calling
if (candidateType.AssemblyQualifiedName == null)
throw new InvalidOperationException($"{candidateType} cannot be used with DynamicTypeAttributeBase"); Type guard
static bool HasAssemblyQualifiedName([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? t) =>
t is not null && t.AssemblyQualifiedName is not null; Try / catch
try
{
var attr = new MyDynamicTypeAttribute(theType);
}
catch (ArgumentException ex) when (ex.ParamName == "type")
{
// fall back to a concrete closed type or log a configuration error
} Prevention
- Never forward bare generic type parameters (typeof(T)) into dynamic-type attributes.
- Apply these attributes only on closed, concrete types.
- Write a startup self-check that constructs all configured attributes in a test.
When it happens
Trigger: Calling a derived attribute's constructor with typeof(T) where T is a generic type parameter; passing a Type instance captured from generic context at runtime; reflection-emit types with no assembly-qualified name.
Common situations: Writing a custom attribute deriving from DynamicTypeAttributeBase and forwarding a generic parameter to 'genericize' helper code; AOT/trimming scenarios; refactor from typeof(ConcreteType) to typeof(T).
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
- The type of collection does not have a parameterless…
- The type of dictionary does not have a parameterless…
- Invalid assembly path. Doesn't contain directory information
- The property [ ] of type [ ] has no setter.
- Value type for root objects are not supported
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/387d006fcfba18ba.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core/Annotations/DynamicTypeAttributeBase.cs:19
// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System.Diagnostics.CodeAnalysis;
namespace Stride.Core.Annotations;
/// <summary>
/// Base class for a dynamic type attribute.
/// </summary>
public abstract class DynamicTypeAttributeBase : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="DynamicTypeAttributeBase"/> class.
/// </summary>
/// <param name="type">The type.</param>
protected DynamicTypeAttributeBase([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type)
{
TypeName = type.AssemblyQualifiedName ?? throw new ArgumentException("The type doesn't have an assembly-qualified name", nameof(type));
}
/// <summary>
/// Initializes a new instance of the <see cref="DynamicTypeAttributeBase"/> class.
/// </summary>
/// <param name="typeName">The type.</param>
protected DynamicTypeAttributeBase(string typeName)
{
TypeName = typeName;
}
/// <summary>
/// Gets the name of the <see cref="DynamicTypeAttributeBase"/> type
/// </summary>
/// <value>The name of the serializable type.</value>
public string TypeName { get; }
}
View on GitHub (pinned to 96fad776d2)