{"record":{"id":"cc065b5dcb9ec904","repo":"infiniflow/ragflow","slug":"100-cc065b","errorCode":"100","errorMessage":"Invalid channel name: {channel}","messagePattern":"Invalid channel name: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"api/apps/restful_apis/user_api.py","lineNumber":169,"sourceCode":"        for channel, config in settings.OAUTH_CONFIG.items():\n            channels.append(\n                {\n                    \"channel\": channel,\n                    \"display_name\": config.get(\"display_name\", channel.title()),\n                    \"icon\": config.get(\"icon\", \"sso\"),\n                }\n            )\n        return get_json_result(data=channels)\n    except Exception as e:\n        logging.exception(e)\n        return get_json_result(data=[], message=f\"Load channels failure, error: {str(e)}\", code=RetCode.EXCEPTION_ERROR)\n\n\n@manager.route(\"/auth/login/<channel>\", methods=[\"GET\"])  # noqa: F821\nasync def oauth_login(channel):\n    channel_config = settings.OAUTH_CONFIG.get(channel)\n    if not channel_config:\n        raise ValueError(f\"Invalid channel name: {channel}\")\n    auth_cli = get_auth_client(channel_config)\n\n    state = get_uuid()\n    session[\"oauth_state\"] = state\n    auth_url = auth_cli.get_authorization_url(state)\n    logging.info(\"OAuth login initiated: channel='%s', state='%s'\", channel, state)\n    return redirect(auth_url)\n\n\n@manager.route(\"/auth/oauth/<channel>/callback\", methods=[\"GET\"])  # noqa: F821\nasync def oauth_callback(channel):\n    \"\"\"\n    Handle the OAuth/OIDC callback for various channels dynamically.\n    \"\"\"\n    try:\n        channel_config = settings.OAUTH_CONFIG.get(channel)\n        if not channel_config:\n            raise ValueError(f\"Invalid channel name: {channel}\")","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/api/apps/restful_apis/user_api.py#L151-L187","documentation":"Raised by GET /auth/login/<channel> when the channel is not present in settings.OAUTH_CONFIG, i.e. no OAuth provider is configured under that name. The route dynamically serves any configured provider (google, github, oidc, ...), so unknown or unconfigured names fail here.","triggerScenarios":"Hitting /api/v1/auth/login/slack when only google/github are keys in OAUTH_CONFIG; typos in the channel path; providers configured but under different key names in settings.","commonSituations":"Frontend links hardcoding a channel the deployment does not enable, env-based OAuth config not loaded (empty OAUTH_CONFIG), or name mismatches between UI and service_conf.yaml oauth section.","solutions":["List configured channels via the channels endpoint (GET /auth/channels) and use one of those names.","Add the provider under settings.OAUTH_CONFIG with the exact key used in the URL.","Fix typos in the channel path segment.","Verify the settings file containing OAUTH_CONFIG is actually loaded by the API server."],"exampleFix":"# before\nGET /api/v1/auth/login/googl\n# after\nGET /api/v1/auth/login/google","handlingStrategy":"validation","validationCode":"from api import settings\n\ndef is_valid_channel(channel: str) -> bool:\n    return channel in (settings.OAUTH_CONFIG or {})\n\nassert is_valid_channel(channel), f\"channel must be one of {list((settings.OAUTH_CONFIG or {}))}\"","typeGuard":"const isValidChannel = (c: string, configured: string[]): c is (typeof configured)[number] =>\n  configured.includes(c);","tryCatchPattern":"try:\n    resp = requests.get(f\"{base}/api/v1/auth/login/{channel}\", allow_redirects=False)\nexcept ValueError as e:\n    if \"Invalid channel\" in str(e):\n        channels = requests.get(f\"{base}/api/v1/auth/channels\").json()\n        raise ValueError(f\"Pick one of {channels}\") from e\n    raise","preventionTips":["Render login buttons from the /auth/channels response, never hardcoded lists.","Automate a config test asserting OAUTH_CONFIG keys match frontend constants."],"tags":["auth","oauth","routing","configuration"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}