{"record":{"id":"89b0ffe67939f8ab","repo":"laurent22/joplin","slug":"non-inline-asset-missing-required-property-name","errorCode":null,"errorMessage":"Non-inline asset missing required property \"name\"","messagePattern":"Non-inline asset missing required property \"name\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/editor/CodeMirror/pluginApi/PluginLoader.ts","lineNumber":166,"sourceCode":"\n\t\t\tloadedPlugin.plugin?.(this.editor);\n\n\t\t\tif (loadedPlugin.codeMirrorOptions) {\n\t\t\t\tfor (const key in loadedPlugin.codeMirrorOptions) {\n\t\t\t\t\tthis.editor.setOption(key, loadedPlugin.codeMirrorOptions[key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (loadedPlugin.assets) {\n\t\t\t\tconst cssStrings = [];\n\n\t\t\t\tfor (const asset of loadedPlugin.assets()) {\n\t\t\t\t\tlet assetText: string = asset.text;\n\t\t\t\t\tlet assetMime: string = asset.mime;\n\n\t\t\t\t\tif (!asset.inline) {\n\t\t\t\t\t\tif (!asset.name) {\n\t\t\t\t\t\t\tthrow new Error('Non-inline asset missing required property \"name\"');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (assetMime !== 'text/css' && !asset.name.endsWith('.css')) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Non-css assets are not supported by the CodeMirror 6 editor. (Asset path: ${asset.name})`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tassetText = await plugin.loadCssAsset(asset.name);\n\t\t\t\t\t\tassetMime = 'text/css';\n\t\t\t\t\t}\n\n\t\t\t\t\tif (assetMime !== 'text/css') {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'Plugin assets must have property \"mime\" set to \"text/css\" or have a filename ending with \".css\"',\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tcssStrings.push(assetText);","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/editor/CodeMirror/pluginApi/PluginLoader.ts#L148-L184","documentation":"Thrown by PluginLoader when iterating loadedPlugin.assets() and encountering an asset with inline === false (or falsy) but no name property. Non-inline assets must reference an external CSS file by name so the loader can call plugin.loadCssAsset(asset.name) to fetch its contents. Without a name the loader cannot resolve the asset.","triggerScenarios":"A plugin asset object is { inline: false, mime: 'text/css' } with text omitted and name omitted; the asset was meant to be inline but inline was not set and text is empty; a typo set name to undefined.","commonSituations":"Plugin author intended an inline asset but forgot to set inline: true and omitted name; asset object built dynamically and name came back undefined; migration from the rich-text editor plugin API which had different asset requirements.","solutions":["If the CSS is a literal string, set asset.inline = true and asset.text = cssString.","If the CSS is a file, set asset.name = 'styles.css' (or the actual filename) and ensure loadCssAsset can resolve it, and omit inline or set it false.","Validate the asset object shape in plugin tests before publishing."],"exampleFix":"// before\nassets: () => [{ mime: 'text/css', text: '' }],\n// after — inline literal\nassets: () => [{ inline: true, mime: 'text/css', text: '.cm-editor { font-size: 14px }' }],","handlingStrategy":"validation","validationCode":"function validateAsset(a) {\n  if (!a.inline && !a.name) throw new Error('Non-inline asset needs a name');\n  if (a.inline && (typeof a.text !== 'string')) throw new Error('Inline asset needs text');\n}\nassets().forEach(validateAsset);","typeGuard":"function isNamedNonInlineAsset(a) { return !a.inline && typeof a.name === 'string' && a.name.length > 0; }","tryCatchPattern":"try {\n  loader.setPlugins(contentScripts);\n} catch (e) {\n  if (/Non-inline asset missing required property/.test(e.message)) {\n    // notify plugin author to add name or switch to inline\n  } else throw e;\n}","preventionTips":["Set inline: true with text for literal CSS, or name: 'file.css' for external CSS.","Add a unit test asserting every asset has either inline+text or a name."],"tags":["editor","codemirror","plugin","asset","css"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}