{"record":{"id":"d6b019267f607f2a","repo":"microsoft/semantic-kernel","slug":"topicid-does-not-match-the-subscription","errorCode":null,"errorMessage":"TopicId does not match the subscription.","messagePattern":"TopicId does not match the subscription\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Agents/Runtime/Core/TypePrefixSubscription.cs","lineNumber":72,"sourceCode":"    /// </summary>\n    /// <param name=\"topic\">The topic to check.</param>\n    /// <returns><c>true</c> if the topic's type starts with the subscription's prefix, <c>false</c> otherwise.</returns>\n    public bool Matches(TopicId topic)\n    {\n        return topic.Type.StartsWith(this.TopicTypePrefix, StringComparison.Ordinal);\n    }\n\n    /// <summary>\n    /// Maps a <see cref=\"TopicId\"/> to an <see cref=\"AgentId\"/>. Should only be called if <see cref=\"Matches\"/> returns true.\n    /// </summary>\n    /// <param name=\"topic\">The topic to map.</param>\n    /// <returns>An <see cref=\"AgentId\"/> representing the agent that should handle the topic.</returns>\n    /// <exception cref=\"InvalidOperationException\">Thrown if the topic does not match the subscription.</exception>\n    public AgentId MapToAgent(TopicId topic)\n    {\n        if (!this.Matches(topic))\n        {\n            throw new InvalidOperationException(\"TopicId does not match the subscription.\");\n        }\n\n        return new AgentId(this.AgentType, topic.Source); // No need for .Name, since AgentType implicitly converts to string\n    }\n\n    /// <summary>\n    /// Determines whether the specified object is equal to the current subscription.\n    /// </summary>\n    /// <param name=\"obj\">The object to compare with the current instance.</param>\n    /// <returns><c>true</c> if the specified object is equal to this instance; otherwise, <c>false</c>.</returns>\n    public override bool Equals([NotNullWhen(true)] object? obj)\n    {\n        return\n            obj is TypePrefixSubscription other &&\n                (this.Id == other.Id ||\n                    (this.AgentType == other.AgentType &&\n                     this.TopicTypePrefix == other.TopicTypePrefix));\n    }","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Agents/Runtime/Core/TypePrefixSubscription.cs#L54-L90","documentation":"TypePrefixSubscription.MapToAgent checks Matches(topic) (topic.Type.StartsWith(TopicTypePrefix, Ordinal)) and throws InvalidOperationException if it does not. The XML doc explicitly states MapToAgent should only be called after Matches returns true. The runtime always calls Matches before MapToAgent, so reaching this throw indicates a logic error or direct misuse.","triggerScenarios":"Calling subscription.MapToAgent(topic) directly without first confirming Matches(topic); a topic whose Type does not start with the configured TopicTypePrefix; concurrent mutation of the topic between the Matches and MapToAgent calls.","commonSituations":"Custom subscription orchestration code that skips the Matches check; a misconfigured prefix that does not correspond to the topics being published; race where topic is rebuilt between calls.","solutions":["Always call `if (subscription.Matches(topic))` before MapToAgent.","Verify the TopicTypePrefix matches (is a prefix of) the topic types you publish.","Let the runtime perform the mapping rather than calling MapToAgent manually."],"exampleFix":"// before\nvar agentId = subscription.MapToAgent(topic);\n\n// after\nif (!subscription.Matches(topic)) { /* skip / log */ return; }\nvar agentId = subscription.MapToAgent(topic);","handlingStrategy":"validation","validationCode":"if (!subscription.Matches(topic))\n{\n    // topic does not match this prefix subscription; skip\n    return;\n}\nAgentId target = subscription.MapToAgent(topic);","typeGuard":"bool Handles(TypePrefixSubscription sub, TopicId t) => t.Type.StartsWith(sub.TopicTypePrefix, StringComparison.Ordinal);","tryCatchPattern":null,"preventionTips":["Always call Matches() before MapToAgent().","Let the runtime perform mapping rather than calling MapToAgent manually.","Ensure TopicTypePrefix is a true prefix of the topic types you publish."],"tags":["subscription","type-prefix","topic","runtime","dotnet"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}