microsoft/aspire · error · InvalidOperationException

Unknown type category

Error message

Unknown type category: {typeRef.Category}

What it means

AtsMarshaller.MarshalToJson serializes a .NET value to JSON for the guest based on the AtsTypeRef's category. Each known category (Primitive, Enum, Dto, Array, List, Dict) has a dedicated branch; this throw is the exhaustive-match fallback, meaning the category value was not one of the recognized enum members. It signals an internal invariant violation: a new AtsTypeCategory member was added without updating the marshaller, or an uninitialized/corrupt category reached the switch.

Solutions

  1. Update/redeploy the host assembly so its marshaller knows the category used by the type reference (matching version).
  2. Check that the AtsTypeRef being marshalled was correctly registered/initialized (not a default value).
  3. Pin host and guest to the same Ats package version so categories match.
  4. If you control the code, add a case for the missing category in the switch expression.
Defensive patterns

Strategy: validation

Validate before calling

if (!Enum.IsDefined(typeof(AtsTypeCategory), typeRef.Category))
    throw new InvalidOperationException($"Category {typeRef.Category} is not marshalled by this host version.");

Type guard

static bool IsKnownCategory(AtsTypeRef t) =>
    t.Category is AtsTypeCategory.Primitive or AtsTypeCategory.Enum or AtsTypeCategory.Dto
        or AtsTypeCategory.Array or AtsTypeCategory.List or AtsTypeCategory.Dict;

Prevention

When it happens

Trigger: Calling MarshalToJson with a typeRef whose Category is not one of AtsTypeCategory.Primitive/Enum/Dto/Array/List/Dict (e.g. a newer category enum value marshalled by an older remote host assembly, or a default(AtsTypeRef) with an undefined category). Reached via SerializeArray -> MarshalToJson when recursing into array element types.

Common situations: Version skew where a guest sends a type reference using a newer AtsTypeCategory than the host's marshaller supports; a newly added AtsTypeCategory enum member whose branch was not implemented; corrupted or default-initialized AtsTypeRef values crossing the remote boundary.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/a2962eefb47de696. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.RemoteHost/Ats/AtsMarshaller.cs:164

            return SerializeCancellationToken(cancellationToken);
        }

        // Handle 'any' type - fall back to runtime type inspection
        if (typeRef.TypeId == TypeSystem.AtsConstants.Any)
        {
            return MarshalToJson(value);
        }

        return typeRef.Category switch
        {
            AtsTypeCategory.Handle => _handles.Marshal(value, typeRef.TypeId),
            AtsTypeCategory.Primitive => SerializePrimitive(value),
            AtsTypeCategory.Enum => JsonValue.Create(value.ToString()),
            AtsTypeCategory.Dto => SerializeDto(value),
            AtsTypeCategory.Array => SerializeArray(value, typeRef.ElementType),
            AtsTypeCategory.List => _handles.Marshal(value, typeRef.TypeId),
            AtsTypeCategory.Dict => _handles.Marshal(value, typeRef.TypeId),
            _ => throw new InvalidOperationException($"Unknown type category: {typeRef.Category}")
        };
    }

    /// <summary>
    /// Marshals a .NET object to JSON for sending to the guest using a declared CLR type.
    /// </summary>
    /// <param name="value">The value to marshal.</param>
    /// <param name="declaredType">The declared type that should be exposed to the guest.</param>
    /// <returns>The JSON representation, or null if the value is null.</returns>
    public JsonNode? MarshalToJson(object? value, Type declaredType)
    {
        if (value == null)
        {
            return null;
        }

        if (declaredType == typeof(object))
        {

View on GitHub (pinned to 25830f84bd)