diff --git a/backend/onyx/server/manage/slack_bot.py b/backend/onyx/server/manage/slack_bot.py
index 53e0d0bbe..ec79e2c21 100644
--- a/backend/onyx/server/manage/slack_bot.py
+++ b/backend/onyx/server/manage/slack_bot.py
@@ -343,7 +343,8 @@ def list_bot_configs(
]
-MAX_CHANNELS = 200
+MAX_SLACK_PAGES = 5
+SLACK_API_CHANNELS_PER_PAGE = 100
@router.get(
@@ -355,8 +356,8 @@ def get_all_channels_from_slack_api(
_: User | None = Depends(current_admin_user),
) -> list[SlackChannel]:
"""
- Fetches all channels from the Slack API.
- If the workspace has 200 or more channels, we raise an error.
+ Fetches channels the bot is a member of from the Slack API.
+ Handles pagination with a limit to avoid excessive API calls.
"""
tokens = fetch_slack_bot_tokens(db_session, bot_id)
if not tokens or "bot_token" not in tokens:
@@ -365,28 +366,60 @@ def get_all_channels_from_slack_api(
)
client = WebClient(token=tokens["bot_token"])
+ all_channels = []
+ next_cursor = None
+ current_page = 0
try:
- response = client.conversations_list(
- types="public_channel,private_channel",
- exclude_archived=True,
- limit=MAX_CHANNELS,
- )
+ # Use users_conversations with limited pagination
+ while current_page < MAX_SLACK_PAGES:
+ current_page += 1
+
+ # Make API call with cursor if we have one
+ if next_cursor:
+ response = client.users_conversations(
+ types="public_channel,private_channel",
+ exclude_archived=True,
+ cursor=next_cursor,
+ limit=SLACK_API_CHANNELS_PER_PAGE,
+ )
+ else:
+ response = client.users_conversations(
+ types="public_channel,private_channel",
+ exclude_archived=True,
+ limit=SLACK_API_CHANNELS_PER_PAGE,
+ )
+
+ # Add channels to our list
+ if "channels" in response and response["channels"]:
+ all_channels.extend(response["channels"])
+
+ # Check if we need to paginate
+ if (
+ "response_metadata" in response
+ and "next_cursor" in response["response_metadata"]
+ ):
+ next_cursor = response["response_metadata"]["next_cursor"]
+ if next_cursor:
+ if current_page == MAX_SLACK_PAGES:
+ raise HTTPException(
+ status_code=400,
+ detail="Workspace has too many channels to paginate over in this call.",
+ )
+ continue
+
+ # If we get here, no more pages
+ break
channels = [
SlackChannel(id=channel["id"], name=channel["name"])
- for channel in response["channels"]
+ for channel in all_channels
]
- if len(channels) == MAX_CHANNELS:
- raise HTTPException(
- status_code=400,
- detail=f"Workspace has {MAX_CHANNELS} or more channels.",
- )
-
return channels
except SlackApiError as e:
+ # Handle rate limiting or other API errors
raise HTTPException(
status_code=500,
detail=f"Error fetching channels from Slack API: {str(e)}",
diff --git a/web/src/app/admin/bots/[bot-id]/channels/SlackChannelConfigFormFields.tsx b/web/src/app/admin/bots/[bot-id]/channels/SlackChannelConfigFormFields.tsx
index 13a80f6bb..92553b97b 100644
--- a/web/src/app/admin/bots/[bot-id]/channels/SlackChannelConfigFormFields.tsx
+++ b/web/src/app/admin/bots/[bot-id]/channels/SlackChannelConfigFormFields.tsx
@@ -199,17 +199,17 @@ export function SlackChannelConfigFormFields({
+
This default configuration will apply across all Slack channels the bot is added to in the Slack workspace, as well as direct messages (DMs), unless disabled.
-+
Warning: Disabling the default configuration means the bot won't respond in Slack channels or DMs unless explicitly configured for them. @@ -238,20 +238,28 @@ export function SlackChannelConfigFormFields({ />
+ Note: This list shows public and private channels where the + bot is a member (up to 500 channels). If you don't see a + channel, make sure the bot is added to that channel in Slack + first, or type the channel name manually. +
+ > )} > )} diff --git a/web/src/app/auth/error/layout.tsx b/web/src/app/auth/error/layout.tsx new file mode 100644 index 000000000..f9e9b6315 --- /dev/null +++ b/web/src/app/auth/error/layout.tsx @@ -0,0 +1,16 @@ +export default function AuthErrorLayout({ + children, +}: { + children: React.ReactNode; +}) { + // Log error to console for debugging + console.error( + "Authentication error page was accessed - this should not happen in normal flow" + ); + + // In a production environment, you might want to send this to your error tracking service + // For example, if using a service like Sentry: + // captureException(new Error("Authentication error page was accessed unexpectedly")); + + return <>{children}>; +} diff --git a/web/src/app/auth/error/page.tsx b/web/src/app/auth/error/page.tsx index 3bee49841..ec2e01e7b 100644 --- a/web/src/app/auth/error/page.tsx +++ b/web/src/app/auth/error/page.tsx @@ -4,6 +4,7 @@ import AuthFlowContainer from "@/components/auth/AuthFlowContainer"; import { Button } from "@/components/ui/button"; import Link from "next/link"; import { FiLogIn } from "react-icons/fi"; +import { NEXT_PUBLIC_CLOUD_ENABLED } from "@/lib/constants"; const Page = () => { return ( @@ -15,19 +16,21 @@ const Page = () => {We encountered an issue while attempting to log you in.
-We recommend trying again. If you continue to experience problems, please reach out to your system administrator for assistance. + {NEXT_PUBLIC_CLOUD_ENABLED && ( + + A member of our team has been automatically notified about this + issue. + + )}