microsoft/semantic-kernel · error · InvalidOperationException

TopicId does not match the subscription.

Error message

TopicId does not match the subscription.

What it means

TypeSubscription.MapToAgent checks Matches(topic) (exact equality topic.Type == TopicType) and throws InvalidOperationException if it does not. As with the prefix variant, the runtime calls Matches before MapToAgent, so this throw signals direct misuse or a topic/subscription mismatch.

Source

Thrown at dotnet/src/Agents/Runtime/Core/TypeSubscription.cs:71

    /// </summary>
    /// <param name="topic">The topic to check.</param>
    /// <returns><c>true</c> if the topic's type matches exactly, <c>false</c> otherwise.</returns>
    public bool Matches(TopicId topic)
    {
        return topic.Type == this.TopicType;
    }

    /// <summary>
    /// Maps a <see cref="TopicId"/> to an <see cref="AgentId"/>. Should only be called if <see cref="Matches"/> returns true.
    /// </summary>
    /// <param name="topic">The topic to map.</param>
    /// <returns>An <see cref="AgentId"/> representing the agent that should handle the topic.</returns>
    /// <exception cref="InvalidOperationException">Thrown if the topic does not match the subscription.</exception>
    public AgentId MapToAgent(TopicId topic)
    {
        if (!this.Matches(topic))
        {
            throw new InvalidOperationException("TopicId does not match the subscription.");
        }

        return new AgentId(this.AgentType, topic.Source);
    }

    /// <summary>
    /// Determines whether the specified object is equal to the current subscription.
    /// </summary>
    /// <param name="obj">The object to compare with the current instance.</param>
    /// <returns><c>true</c> if the specified object is equal to this instance; otherwise, <c>false</c>.</returns>
    public override bool Equals([NotNullWhen(true)] object? obj)
    {
        return
            obj is TypeSubscription other &&
                (this.Id == other.Id ||
                    (this.AgentType == other.AgentType &&
                        this.TopicType == other.TopicType));
    }

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Guard with `if (subscription.Matches(topic))` before MapToAgent.
  2. Ensure the published topic type exactly equals the subscription's TopicType (including casing).
  3. Prefer using the runtime's publish path so Matches is always checked.

Example fix

// before
var agentId = subscription.MapToAgent(topic);

// after
if (!subscription.Matches(topic)) return;
var agentId = subscription.MapToAgent(topic);
Defensive patterns

Strategy: validation

Validate before calling

if (!subscription.Matches(topic))
{
    return; // topic type does not exactly match
}
AgentId target = subscription.MapToAgent(topic);

Type guard

bool Handles(TypeSubscription sub, TopicId t) => string.Equals(t.Type, sub.TopicType, StringComparison.Ordinal);

Prevention

When it happens

Trigger: Calling subscription.MapToAgent(topic) directly without a prior Matches check; a topic whose Type differs from the subscription's exact TopicType; a typo or casing mismatch between published topic type and TopicType (matching is ordinal/case-sensitive).

Common situations: Casing differences between the published TopicId.Type and the registered TopicType; manual mapping code; publishing to a topic type that has no matching subscription.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/26a70157d50029ea. Report an issue: GitHub.