microsoft/semantic-kernel · error · ValueError

Invalid topic id: {topic_id}

Error message

Invalid topic id: {topic_id}

What it means

Raised by TopicId.from_str when the input does not split into exactly two parts on the first '/'. from_str expects the format type/source; a string with no '/' yields a single part and raises ValueError. (A string like '/source' yields an empty type, which then fails the regex check and raises the invalid-type error instead.)

Source

Thrown at python/semantic_kernel/agents/runtime/core/topic.py:56

    Learn more here: https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#source-1
    """

    def __post_init__(self) -> None:
        """Validate the topic type and source."""
        if is_valid_topic_type(self.type) is False:
            raise ValueError(f"Invalid topic type: {self.type}. Must match the pattern: ^[\\w\\-\\.\\:\\=]+\\Z")

    def __str__(self) -> str:
        """Convert the TopicId to a string."""
        return f"{self.type}/{self.source}"

    @classmethod
    def from_str(cls, topic_id: str) -> Self:
        """Convert a string of the format ``type/source`` into a TopicId."""
        items = topic_id.split("/", maxsplit=1)
        if len(items) != 2:
            raise ValueError(f"Invalid topic id: {topic_id}")
        type, source = items[0], items[1]
        return cls(type, source)

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Ensure the string is in 'type/source' format with at least one '/'.
  2. Validate the presence of '/' (and a non-empty type) before calling from_str.
  3. If you already have the parts, build TopicId directly via TopicId(type, source).

Example fix

// before
topic = TopicId.from_str('mytopic')  # no '/' -> ValueError

// after
topic = TopicId.from_str('mytopic/source-1')
# or, when you already have the parts:
topic = TopicId(type='mytopic', source='source-1')
Defensive patterns

Strategy: validation

Validate before calling

def is_valid_topic_id_str(s: str) -> bool:
    parts = s.split('/', maxsplit=1)
    return len(parts) == 2 and bool(parts[0]) and bool(parts[1])

Type guard

def looks_like_topic_id_str(s: str) -> bool:
    parts = s.split('/', maxsplit=1)
    return len(parts) == 2 and bool(parts[0])

Prevention

When it happens

Trigger: Calling TopicId.from_str('novalue') with no slash; calling from_str('') on an empty string; any input missing the type/source separator.

Common situations: Parsing user input or configuration that lacks the type/source format; constructing the string with an off-by-one; passing a bare topic name.

Related errors


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