toeverything/AFFiNE · info · BlockSuiteError

UserAbortError

UserAbortError

Error message

Aborted by user

What it means

importMindmap (gfx/mindmap/src/toolbar/utils/import-mindmap.ts:13-20) opens a native single-file picker via openSingleFileWith('MindMap'); when the user dismisses the dialog the returned file is null and UserAbortError 'Aborted by user' is thrown. This is expected control flow (the user declined to choose a file), not a failure — BlockSuiteError.isFatal is false for this code.

Source

Thrown at blocksuite/affine/gfx/mindmap/src/toolbar/utils/import-mindmap.ts:18

import { openSingleFileWith } from '@blocksuite/affine-shared/utils';
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
import type { Bound } from '@blocksuite/global/gfx';
import c from 'simple-xml-to-json';

type MindMapNode = {
  children: MindMapNode[];
  text: string;
  xywh?: string;
  title?: string;
  layoutType?: 'left' | 'right';
};

export async function importMindmap(bound: Bound): Promise<MindMapNode> {
  const file = await openSingleFileWith('MindMap');

  if (!file) {
    throw new BlockSuiteError(ErrorCode.UserAbortError, 'Aborted by user');
  }

  let result;

  if (file.name.endsWith('.mm')) {
    result = await parseMmFile(file);
  } else if (file.name.endsWith('.opml') || file.name.endsWith('.xml')) {
    result = await parseOPMLFile(file);
  } else {
    throw new BlockSuiteError(ErrorCode.ParsingError, 'Unsupported file type');
  }

  if (result) {
    result.xywh = bound.serialize();
  }

  return result;
}

View on GitHub (pinned to b4c8548c09)

Solutions

  1. Catch BlockSuiteError with code UserAbortError and return silently (no toast)
  2. Distinguish it from ParsingError so only genuine parse failures surface to the user

Example fix

// before
const mindmap = await importMindmap(bound); // cancel -> unhandled UserAbortError

// after
try {
  const mindmap = await importMindmap(bound);
} catch (e) {
  if (e instanceof BlockSuiteError && e.code === BlockSuiteError.ErrorCode.UserAbortError) return;
  throw e;
}
Defensive patterns

Strategy: try-catch

Try / catch

import { BlockSuiteError } from '@blocksuite/global/exceptions';

try {
  const mindmap = await importMindmap(bound);
} catch (e) {
  if (e instanceof BlockSuiteError && e.code === BlockSuiteError.ErrorCode.UserAbortError) {
    return; // user closed the picker: silent no-op
  }
  throw e;
}

Prevention

When it happens

Trigger: User clicks Cancel or presses Escape in the file picker opened from the mindmap toolbar import action; the OS dialog is closed without a selection.

Common situations: Any mindmap-import button handler that awaits importMindmap without distinguishing user cancellation from real failures, showing an error toast on a plain cancel.

Related errors


AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18). Data as JSON: /api/errors/944d44c36b45b04a. Report an issue: GitHub.