mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 23:41:12 +08:00
## Summary Fixes #15790. Every Discord sync launched from the current Web UI crashes immediately with: ``` 'list' object has no attribute 'split' ``` The error is raised in [rag/svr/sync_data_source.py:650-651](rag/svr/sync_data_source.py#L650-L651): ```python server_ids=server_ids.split(",") if server_ids else [], channel_names=channel_names.split(",") if channel_names else [], ``` ### Root cause Three independent bugs stack here, all in the Discord branch of `sync_data_source.py`: 1. **Type mismatch (the user's exact error).** The current form at [web/src/pages/user-setting/data-source/constant/index.tsx:833-843](web/src/pages/user-setting/data-source/constant/index.tsx#L833-L843) uses `FormFieldType.Tag` for both **Server IDs** and **Channels**: ```tsx { label: 'Server IDs', name: 'config.server_ids', type: FormFieldType.Tag, required: false }, { label: 'Channels', name: 'config.channels', type: FormFieldType.Tag, required: false }, ``` Tag inputs serialise to **lists**, not comma-separated strings. The backend `.split(",")` then explodes on the very first sync. 2. **Field-name mismatch.** The form writes `config.channels`. The backend reads `self.conf.get("channel_names", None)`. Even if `.split(",")` were fixed, channels would silently be empty for every UI-created source. 3. **Int conversion missing.** [common/data_source/discord_connector.py:82](common/data_source/discord_connector.py#L82) types `server_ids` as `list[int]` (Discord guild IDs are integers); the previous `.split(",")` produced strings, so the `channel.guild.id not in server_ids` filter at [discord_connector.py:92](common/data_source/discord_connector.py#L92) silently never matched. So even the configurations that didn't crash were also broken — there is no path through the current code that actually filtered by server id from a UI-created source. ### Fix A 39-line patch in one function: - New `Discord._coerce_str_list` static method: accepts `None` / `""` / `list` / `tuple` / `set` / scalar / comma-separated str, returns a clean `list[str]` with whitespace trimmed and empty entries dropped. Smoke-tested against the 10 input shapes that can hit it (see Test plan). - `_generate` reads `config.channels` first (the form's actual key) and falls back to `config.channel_names`, so SDK callers and legacy configs that already shipped with the old key keep working. - `server_ids` is coerced to `list[int]`. Non-integer entries are logged and dropped instead of crashing the sync, so a single malformed tag from the form doesn't tank the rest of the run. ### What this PR does NOT change - **Web form key (`config.channels`)** — kept as-is. Renaming it to `channel_names` would force a UI migration and break in-flight configs; the backend fallback solves the same problem more safely. - **`common/data_source/discord_connector.py`** — its signature was already correct. - **Other connectors (Slack, Gmail, Confluence, etc.)** — they don't crash today and were not in the issue's scope. ## Test plan `Discord._coerce_str_list` has been exercised against all ten realistic input shapes — list, tuple, set, comma-separated string, str with extra whitespace, empty entries, integers from a Tag input, None, empty list, single trailing comma. All pass.