laurent22/joplin · error · Error

Plugin assets must have property "mime" set to "text/css" or

Error message

Plugin assets must have property "mime" set to "text/css" or have a filename ending with ".css"

What it means

Thrown after the inline/non-inline branch when assetMime is still not 'text/css'. This catches inline assets whose mime was wrong or missing (non-inline assets that passed the earlier check have already had assetMime normalized to text/css on line 175). It is the final guarantee that only CSS reaches addStyles.

Source

Thrown at packages/editor/CodeMirror/pluginApi/PluginLoader.ts:179

					let assetText: string = asset.text;
					let assetMime: string = asset.mime;

					if (!asset.inline) {
						if (!asset.name) {
							throw new Error('Non-inline asset missing required property "name"');
						}
						if (assetMime !== 'text/css' && !asset.name.endsWith('.css')) {
							throw new Error(
								`Non-css assets are not supported by the CodeMirror 6 editor. (Asset path: ${asset.name})`,
							);
						}

						assetText = await plugin.loadCssAsset(asset.name);
						assetMime = 'text/css';
					}

					if (assetMime !== 'text/css') {
						throw new Error(
							'Plugin assets must have property "mime" set to "text/css" or have a filename ending with ".css"',
						);
					}

					cssStrings.push(assetText);
				}

				addStyles(cssStrings);
			}
		});

		this.loadedContentScriptIds.push(contentScriptToId(plugin));
	}

	public remove() {
		this.pluginScriptsContainer.remove();
	}
}

View on GitHub (pinned to 2654b33620)

Solutions

  1. Set asset.mime = 'text/css' on every inline CSS asset.
  2. Remove the asset if it is not CSS.
  3. Construct assets via a helper that defaults mime to 'text/css'.

Example fix

// before
assets: () => [{ inline: true, text: '.cm-editor { color: red }' }],
// after
assets: () => [{ inline: true, mime: 'text/css', text: '.cm-editor { color: red }' }],
Defensive patterns

Strategy: validation

Validate before calling

function assertInlineCssMime(a) {
  if (a.inline && a.mime !== 'text/css') throw new Error('Inline asset must be text/css');
}
assets().forEach(assertInlineCssMime);

Type guard

function isInlineCssAsset(a) { return a.inline === true && a.mime === 'text/css'; }

Try / catch

try {
  loader.setPlugins(contentScripts);
} catch (e) {
  if (/must have property "mime"/.test(e.message)) {
    // default mime to text/css and retry, or skip
  } else throw e;
}

Prevention

When it happens

Trigger: An inline asset with mime omitted or set to something other than 'text/css' (e.g. 'text/javascript', undefined); an inline asset with text present but mime = 'application/json'. Because name is irrelevant for inline assets, the .css-extension fallback does not apply here.

Common situations: Plugin author set inline: true and text but forgot mime; mime was set to a wrong value copied from another asset; the asset object was constructed with mime = null.

Related errors


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