block/buzz · error · Error
Choose a channel first.
Error message
Choose a channel first.
What it means
WorkflowMessagePicker's infinite history query only runs when `channelId` is truthy (`enabled: Boolean(channelId)`), but the queryFn re-checks and throws 'Choose a channel first.' as a defensive guard. This means the fetch function was invoked without a channel id — normally impossible while `enabled` gates it, so the throw surfaces a state/timing bug or a direct call rather than an expected condition.
Source
Thrown at desktop/src/features/workflows/ui/WorkflowMessagePicker.tsx:76
onEscape?: () => void;
value: string;
}) {
const optionRefs = React.useRef(new Map<string, HTMLButtonElement>());
const [query, setQuery] = React.useState("");
const [activeIndex, setActiveIndex] = React.useState<number | null>(null);
const trimmedQuery = query.trim();
const deferredQuery = React.useDeferredValue(trimmedQuery);
const normalizedQuery = deferredQuery.toLowerCase();
const selectedId = normalizeMessageEventId(value);
const directId = normalizeMessageEventId(query);
const lookupId = directId ?? selectedId;
const historyQuery = useInfiniteQuery({
enabled: Boolean(channelId),
initialPageParam: null as ChannelPageCursor | null,
queryKey: ["workflow-message-picker", channelId],
queryFn: async ({ pageParam }) => {
if (!channelId) throw new Error("Choose a channel first.");
return parseChannelWindowResponse(
await getChannelWindowEvents(channelId, pageParam, PAGE_SIZE),
channelId,
pageParam,
);
},
getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
staleTime: 30_000,
});
const searchQuery = useSearchMessagesQuery(deferredQuery, {
channelId: channelId ?? undefined,
enabled: Boolean(channelId && normalizedQuery && !directId),
limit: 30,
minimumQueryLength: 1,
});
const exactQuery = useQuery({
enabled: Boolean(channelId && lookupId),
queryKey: ["workflow-message-picker-exact", channelId, lookupId],View on GitHub (pinned to dad5a33865)
Solutions
- Select a channel so `channelId` is set before triggering the history query or refetch.
- Gate any manual `refetch()` on `Boolean(channelId)` so it is never called without a channel.
- Check why React Query ran the query despite `enabled: Boolean(channelId)` — look for imperative queryClient.fetchQuery calls bypassing the gate.
- In tests, provide a channelId fixture or mock the query before rendering the picker.
Example fix
// before
if (!channelId) throw new Error("Choose a channel first.");
// after — caller guards before refetch
const pickChannel = async () => {
if (!channelId) return; // UI already requires a selection
await historyQuery.refetch();
}; Defensive patterns
Strategy: validation
Validate before calling
if (!channelId) return null; // or render a 'pick a channel' placeholder
const historyQuery = useInfiniteQuery({
enabled: Boolean(channelId),
queryKey: ["workflow-message-picker", channelId],
queryFn: ({ pageParam }) => getChannelWindowEvents(channelId!, pageParam, PAGE_SIZE),
}); Type guard
const hasChannel = (id: string | null | undefined): id is string => typeof id === "string" && id.length > 0;
Try / catch
try {
await historyQuery.refetch();
} catch (e) {
if (e instanceof Error && e.message === "Choose a channel first.") return;
throw e;
} Prevention
- Only call refetch() when Boolean(channelId) is true.
- Render the picker only after a channel is selected.
- Avoid imperative queryClient.fetch* calls that bypass the enabled gate.
When it happens
Trigger: Invoking `historyQuery.refetch()` (or the queryFn) while `channelId` is null/undefined; the picker being rendered and forced to fetch before a channel is selected; code that manually calls the query function outside React Query's enabled gating.
Common situations: Opening the workflow message picker before selecting a channel and triggering a refetch; remount race where stale query state re-fires the queryFn; automated tests calling the query function directly; channelId cleared (channel deleted or switched) while a refetch is in flight.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Choose a project.
- plugin.json unknown key "{key}"
- plugin.json defaults: unknown key "{key}"
- plugin.json defaults.triggers: unknown key "{key}"
- skill {label}: name "{name_str}" differs from directory name
AI-assisted analysis of block/buzz@dad5a33865 (2026-08-30).
Data as JSON: /api/errors/c621b0e0e93b9c8d.
Report an issue: GitHub.