toeverything/AFFiNE · error · BlockSuiteError

ParsingError

ParsingError

Error message

Unsupported file type

What it means

After a file is chosen, importMindmap (import-mindmap.ts:21-29) only accepts FreeMind .mm files and .opml/.xml outlines; any other extension throws ParsingError 'Unsupported file type'. The check is by filename extension only, so a mismatched payload renamed to .mm will pass this check and fail later in parsing.

Solutions

  1. Pre-check the extension before calling importMindmap and show a friendly 'Supported: .mm, .opml, .xml' message
  2. Set the picker's accept filter to .mm,.opml,.xml if the file-dialog API supports it
  3. Normalize with file.name.toLowerCase().endsWith(...) before dispatching to a parser

Example fix

// before
const mindmap = await importMindmap(bound); // picks notes.txt -> ParsingError

// after
const name = file.name.toLowerCase();
if (!name.endsWith('.mm') && !name.endsWith('.opml') && !name.endsWith('.xml')) {
  toast('Unsupported file type. Use .mm, .opml or .xml.');
  return;
}
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED = ['.mm', '.opml', '.xml'] as const;

const isSupportedMindmapFile = (file: File): boolean => {
  const name = file.name.toLowerCase();
  return SUPPORTED.some(ext => name.endsWith(ext));
};

if (!isSupportedMindmapFile(file)) {
  toast('Unsupported file type. Use .mm, .opml or .xml.');
  return;
}

Type guard

function isSupportedMindmapFile(file: File): boolean {
  const n = file.name.toLowerCase();
  return n.endsWith('.mm') || n.endsWith('.opml') || n.endsWith('.xml');
}

Try / catch

try {
  const mindmap = await importMindmap(bound);
} catch (e) {
  if (e instanceof BlockSuiteError && e.code === BlockSuiteError.ErrorCode.ParsingError) {
    toast('Unsupported file type. Use .mm, .opml or .xml.');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: User selects .xlsx/.md/.json or an extension-less export in the mindmap import picker; browsers/platforms that do not enforce the accept filter; files with trailing spaces or unusual case in the extension (endsWith is case-sensitive, so '.MM' also throws).

Common situations: File picker accept filter missing or ignored by the OS dialog; users trying to import OPML variants with uncommon extensions; case-sensitive extension mismatch on macOS/Windows exports.

Related errors


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

Appendix: source

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

  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;
}

function readAsText(file: File) {
  return file.text();
}

type RawMmNode = {
  node?: {
    TEXT: string;
    POSITION: 'left' | 'right';
    children?: RawMmNode[];

View on GitHub (pinned to b4c8548c09)