laurent22/joplin · error · Error

Cannot find library ${library}

Error message

Cannot find library ${library}

What it means

Thrown by codeMirrorRequire (the plugin-facing require) when the requested library name is not in the curated libraryNameToPackage whitelist AND window.require is either not a function or also cannot resolve it. The whitelist (lines 22-37) exposes only @codemirror/* and @lezer/* packages so plugins cannot pull arbitrary Node modules or duplicate CodeMirror copies. On mobile window.require is absent, so any non-whitelisted library always fails.

Source

Thrown at packages/editor/CodeMirror/pluginApi/codeMirrorRequire.ts:53

	'@lezer/markdown': lezerMarkdown,
	'@lezer/highlight': lezerHighlight,
};

const codeMirrorRequire = (library: string) => {
	// Here, we use hasOwnProperty instead of "in" to prevent
	// require("constructor") or require("__proto__") from returning
	// a constructor or prototype object.
	if (libraryNameToPackage.hasOwnProperty(library)) {
		return libraryNameToPackage[library];
	}

	// Although window.require doesn't work on mobile, some desktop-only plugins
	// originally developed for CodeMirror 5 rely on it.
	if (typeof window.require === 'function') {
		return window.require(library);
	}

	throw new Error(`Cannot find library ${library}`);
};

export default codeMirrorRequire;

View on GitHub (pinned to 2654b33620)

Solutions

  1. Only require packages in the runtime whitelist: @codemirror/{view,state,search,language,autocomplete,commands,lint,lang-html,lang-markdown,language-data} and @lezer/{common,markdown,highlight}.
  2. If you need @codemirror/highlight specifically, note it is missing from the runtime map — file a Joplin issue or use @lezer/highlight instead.
  3. Bundle any other dependency into the plugin's own webpack build instead of require()-ing it at runtime.
  4. Check the exact spelling/version of the package name against the whitelist keys.

Example fix

// before
const { EditorView } = require('codemirror');
// after — use the whitelisted CM6 package name
const { EditorView } = require('@codemirror/view');
Defensive patterns

Strategy: type-guard

Validate before calling

const WHITELIST = new Set([
  '@codemirror/view','@codemirror/state','@codemirror/search','@codemirror/language',
  '@codemirror/autocomplete','@codemirror/commands','@codemirror/lint',
  '@codemirror/lang-html','@codemirror/lang-markdown','@codemirror/language-data',
  '@lezer/common','@lezer/markdown','@lezer/highlight',
]);
function safeRequire(name) {
  if (!WHITELIST.has(name)) throw new Error(`Unsupported require: ${name}`);
  return require(name);
}

Type guard

function isWhitelistedLibrary(name) {
  return WHITELIST.has(name);
}

Try / catch

try {
  return codeMirrorRequire(lib);
} catch (e) {
  if (/Cannot find library/.test(e.message)) {
    // bundle the dep into the plugin instead, or suggest an alternative
  } else throw e;
}

Prevention

When it happens

Trigger: A plugin calls require('codemirror') (the v5 name) which is not whitelisted; require('@codemirror/highlight') which is absent from the map despite being listed in webpack externals (note: the map includes lang-html, lang-markdown, etc. but NOT @codemirror/highlight); require('react') or any third-party module; require misspelled a whitelisted package name.

Common situations: CM5 plugin ported to CM6 still calling require('codemirror'); plugin tries to require @codemirror/highlight (present in webpack externals list at line 235 but NOT in the runtime whitelist map at lines 22-37 — a known gap); plugin requires a transitive dependency not exposed by design.

Related errors


AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12). Data as JSON: /api/errors/0420a6aed1d52f74. Report an issue: GitHub.