infiniflow/ragflow · error · ValueError

[Categorize] 'To' of category {k} can not be empty!

Error message

[Categorize] 'To' of category {k} can not be empty!

What it means

Raised by CategorizeParam.check (agent/component/categorize.py) when a category entry's dict lacks a truthy 'to' value. 'to' names the downstream component/branch the conversation routes to when the LLM picks that category; without it routing is undefined, so validation fails with the category name in the message.

Source

Thrown at agent/component/categorize.py:50

    Define the categorize component parameters.
    """

    def __init__(self):
        super().__init__()
        self.category_description = {}
        self.query = "sys.query"
        self.message_history_window_size = 1
        self.update_prompt()

    def check(self):
        if not isinstance(self.message_history_window_size, int) or self.message_history_window_size < 0:
            raise ValueError("[Categorize] Message window size cannot be negative")
        self.check_empty(self.category_description, "[Categorize] Category examples")
        for k, v in self.category_description.items():
            if not k:
                raise ValueError("[Categorize] Category name can not be empty!")
            if not v.get("to"):
                raise ValueError(f"[Categorize] 'To' of category {k} can not be empty!")

    def get_input_form(self) -> dict[str, dict]:
        return {"query": {"type": "line", "name": "Query"}}

    def update_prompt(self):
        cate_lines = []
        for c, desc in self.category_description.items():
            for line in desc.get("examples", []):
                if not line:
                    continue
                cate_lines.append('USER: "' + re.sub(r"\n", "    ", line, flags=re.DOTALL) + '" → ' + c)

        descriptions = []
        for c, desc in self.category_description.items():
            if desc.get("description"):
                descriptions.append("\n------\nCategory: {}\nDescription: {}".format(c, desc["description"]))

        self.sys_prompt = """

View on GitHub (pinned to 554fb1133a)

Solutions

  1. In the Categorize editor, connect every category's output to a target component so 'to' is populated
  2. Inspect the canvas JSON category_description entries and fill any empty "to" with a valid component id
  3. After deleting or renaming downstream components, re-open the Categorize component and re-link each category

Example fix

# before
"category_description": {"faq": {"examples": [...], "to": ""}}

# after
"category_description": {"faq": {"examples": [...], "to": "Generate:0"}}
Defensive patterns

Strategy: validation

Validate before calling

valid_component_ids = {c['id'] for c in canvas_components}
for name, spec in categories.items():
    if not spec.get('to') or spec['to'].split(':')[0] not in valid_component_ids:
        raise ValueError(f"Category '{name}' must route to an existing component")

Type guard

def all_categories_routed(categories: dict) -> bool:
    return all(v.get('to') for v in categories.values())

Try / catch

try:
    param.check()
except ValueError as e:
    if "'To' of category" in str(e):
        flag_canvas_incomplete('Connect every Categorize category to a downstream component')
    else:
        raise

Prevention

When it happens

Trigger: Adding a category with a name and examples but not connecting its output to another component in the canvas; or the 'to' field being an empty string in the JSON. Fires during check() when the canvas is saved or executed.

Common situations: Building a new categorize node and forgetting to wire its outgoing connections; deleting a downstream component and leaving the category's 'to' dangling/blank; importing a canvas whose component ids changed so 'to' was reset.

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/cf855e5220efdf83. Report an issue: GitHub.