toeverything/AFFiNE · error · BlockSuiteError
DatabaseBlockError
DatabaseBlockError
Error message
Unknown arrow keys, only support: up, down, left, and right keys.
What it means
KanbanSelectionController.getNextFocusCard (kanban/pc/controller/selection.ts:307-385) walks an if-chain over nextPosition ('up','down','left','right'); the trailing throw at :381 fires only when the caller passes a value outside that union. In well-typed TypeScript code it is unreachable; at runtime it appears when key names are forwarded un-narrowed (e.g. raw KeyboardEvent.key like 'ArrowUp') or via any-casts.
Solutions
- Map KeyboardEvent.key to the union ('ArrowUp'->'up', 'ArrowDown'->'down', 'ArrowLeft'->'left', 'ArrowRight'->'right') before calling
- Keep the parameter typed as the literal union and avoid any/string casts at event boundaries
- Early-return for unrecognized keys instead of forwarding them
Example fix
// before
controller.getNextFocusCard(selection, index, key as any); // key = 'ArrowUp' -> throws
// after
const map: Record<string, 'up'|'down'|'left'|'right'> = {
ArrowUp: 'up', ArrowDown: 'down', ArrowLeft: 'left', ArrowRight: 'right',
};
const dir = map[key];
if (dir) controller.getNextFocusCard(selection, index, dir); Defensive patterns
Strategy: type-guard
Validate before calling
const KEY_TO_DIRECTION: Record<string, 'up' | 'down' | 'left' | 'right'> = {
ArrowUp: 'up',
ArrowDown: 'down',
ArrowLeft: 'left',
ArrowRight: 'right',
};
const direction = KEY_TO_DIRECTION[event.key];
if (direction) {
controller.getNextFocusCard(selection, index, direction);
} Type guard
type Direction = 'up' | 'down' | 'left' | 'right'; const isDirection = (d: string): d is Direction => d === 'up' || d === 'down' || d === 'left' || d === 'right';
Prevention
- Translate KeyboardEvent.key to the canonical direction union at the event boundary
- Keep getNextFocusCard's parameter typed as the literal union; never cast from string/any
- Ignore unrecognized keys instead of forwarding them
When it happens
Trigger: A custom hotkey/keyboard handler mapping KeyboardEvent.key directly to getNextFocusCard without translating 'ArrowUp' to 'up'; JS callers or string-cast code bypassing the 'up'|'down'|'left'|'right' literal-union type.
Common situations: Custom kanban keyboard navigation extensions; tests calling the private controller with arbitrary strings; refactors that widen the direction parameter to string.
Related errors
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/eecfe0d617dbccec.
Report an issue: GitHub.
Appendix: source
Thrown at blocksuite/affine/data-view/src/view-presets/kanban/pc/controller/selection.ts:381
if (nextPosition === 'right') {
return getNextGroupFocusElement(
this.host,
groups,
selection,
groupIndex => (groupIndex === groups.length - 1 ? 0 : groupIndex + 1)
);
}
if (nextPosition === 'left') {
return getNextGroupFocusElement(
this.host,
groups,
selection,
groupIndex => (groupIndex === 0 ? groups.length - 1 : groupIndex - 1)
);
}
throw new BlockSuiteError(
ErrorCode.DatabaseBlockError,
'Unknown arrow keys, only support: up, down, left, and right keys.'
);
}
getNextFocusCell(
selection: KanbanCellSelection,
index: number,
nextPosition: 'up' | 'down' | 'left' | 'right'
):
| {
cell: KanbanCell;
cardId?: string;
groupKey?: string;
}
| undefined {
const host = this.host;
if (!host) {View on GitHub (pinned to b4c8548c09)