> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lumen.bjanczak.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting Lumen Editor: Fix Common Issues Fast

> Diagnose and fix common Lumen Editor issues: rendering failures, content saving problems, image upload errors, and unexpected paste behaviour.

Most problems with Lumen Editor fall into a small set of categories: the editor fails to appear, content is not persisted, images silently fail to upload, or pasted content looks different from the source. This page walks through each issue, explains why it happens, and shows you exactly what to check or change to resolve it.

## Common Issues

<Accordion title="Editor is not rendering">
  If the editor container appears blank or the toolbar is missing, work through the following checks in order.

  **1. Ensure the target element exists before initialisation**

  Lumen attaches to a DOM element you supply. If that element does not exist at the time you call `new Editor()`, initialisation silently fails.

  ```js theme={null}
  // ✅ Wait for the DOM to be ready
  document.addEventListener('DOMContentLoaded', () => {
    const editor = new Editor('#my-editor', options);
  });
  ```

  **2. Import the theme stylesheet**

  Without `theme.css`, the editor's toolbar and content area have no layout styles and may collapse to zero height.

  ```js theme={null}
  import 'lumen-editor/theme.css';
  ```

  **3. Give the container a height**

  The editor fills the height of its container. If the container has no explicit height — and no content to stretch it — the editor will not be visible.

  ```css theme={null}
  #my-editor {
    height: 400px; /* or min-height */
  }
  ```
</Accordion>

<Accordion title="Styles are not applied">
  If the editor renders but looks unstyled — toolbar icons are missing, fonts are wrong, or the content area has no border — the most common cause is a missing CSS import.

  Make sure you import the Lumen theme **before** your own stylesheets so you can override individual rules where needed:

  ```js theme={null}
  import 'lumen-editor/theme.css';
  import './your-styles.css'; // overrides go here
  ```

  If you are using a bundler that processes CSS (Vite, webpack, Parcel), confirm the import resolves correctly by checking your bundler's output or the Network panel in DevTools.
</Accordion>

<Accordion title="Content is not saving">
  **autoSave key collision**

  The `autoSave` feature persists content to `localStorage` using a key you provide. If two editor instances share the same key, they will overwrite each other's data.

  ```js theme={null}
  const editor = new Editor('#editor', {
    autoSave: { key: 'post-draft-42' }, // use a unique key per editor instance
  });
  ```

  **Reading the latest content on change**

  If you are manually saving content, call `getHTML()` inside the `change` event handler — not outside it. Calling it at a fixed point in time will return a stale snapshot.

  ```js theme={null}
  editor.on('change', () => {
    const html = editor.getHTML();
    saveToServer(html);
  });
  ```
</Accordion>

<Accordion title="Images are not uploading">
  **uploadImage must return a URL string**

  If your `uploadImage` handler throws an error or returns `undefined`, Lumen silently skips the image insertion. Make sure the function always resolves to a URL string.

  ```js theme={null}
  const editor = new Editor('#editor', {
    uploadImage: async (file) => {
      const response = await fetch('/api/upload', {
        method: 'POST',
        body: createFormData(file),
      });
      const { url } = await response.json();
      return url; // must be a string
    },
  });
  ```

  **Listen to the error event for diagnostics**

  Upload failures surface through the `error` event. Attach a listener during development to catch issues early:

  ```js theme={null}
  editor.on('error', (e) => {
    console.warn(e.code, e.message);
  });
  ```

  **Image validation rules**

  Lumen validates images before calling `uploadImage`. An image is rejected if it fails any of the following checks:

  * MIME type is not an accepted image type
  * Magic bytes do not match the declared MIME type
  * File size exceeds the limit (default **5 MB**)

  <Warning>
    If an image fails validation, `uploadImage` is never called and no error is thrown to your handler. The rejection is reported exclusively through the `error` event.
  </Warning>
</Accordion>

<Accordion title="Pasted content loses formatting">
  **Sanitization is intentional**

  When you paste HTML into Lumen Editor, the content passes through a built-in, DOM-based sanitizer that strips any tags and attributes not on the allowlist. This is a security feature, not a bug — it prevents XSS payloads from entering the editor via the clipboard.

  Plain text pasted from any source is always safe and is never modified.

  **Allowing additional tags and attributes**

  If your workflow requires preserving specific tags or attributes that Lumen strips by default, configure the `sanitize` option:

  ```js theme={null}
  const editor = new Editor('#editor', {
    sanitize: {
      allowTags: ['mark', 'abbr'],
      allowAttributes: { abbr: ['title'] },
    },
  });
  ```

  <Note>
    Extend the allowlist only for tags and attributes you fully trust. Adding permissive rules — such as allowing `style` or event handler attributes — can reintroduce XSS risk.
  </Note>
</Accordion>

<Accordion title="TypeScript errors">
  **Types are included in the package**

  Lumen Editor ships its own TypeScript type definitions — you do not need to install a separate `@types/lumen-editor` package. The named export works directly:

  ```ts theme={null}
  import { Editor } from 'lumen-editor';
  ```

  **Exported types**

  The following types are available for import alongside `Editor`:

  ```ts theme={null}
  import type {
    EditorOptions,
    EditorModule,
    EditorPlugin,
    EditorEvent,
  } from 'lumen-editor';
  ```

  If your editor reports that the module cannot be found, confirm that `moduleResolution` in your `tsconfig.json` is set to `"bundler"`, `"node16"`, or `"nodenext"` — older `"node"` resolution may not pick up the `exports` field in `package.json`.
</Accordion>

<Accordion title="CSP violations">
  **Lumen Editor is CSP-compatible by design**

  Lumen does not use `eval`, `new Function`, inline `<script>` tags, or dynamic script injection. This means it works with strict Content Security Policies without any special exceptions.

  If you use `strict-dynamic` in your CSP header, you do **not** need to add a nonce or hash for Lumen Editor itself.

  A policy such as the following is fully compatible:

  ```http theme={null}
  Content-Security-Policy:
    default-src 'self';
    script-src 'self' 'strict-dynamic';
    style-src 'self';
  ```

  If you are seeing CSP violations in the console while using Lumen, the violation is most likely originating from another library, a browser extension, or an inline script elsewhere on the page — not from Lumen Editor itself.
</Accordion>

## Debugging Tips

When an issue is not immediately obvious, use the `error` event as your first diagnostic tool. Lumen surfaces internal errors — upload failures, sanitizer rejections, plugin faults — with a structured `code` and `message`:

```js theme={null}
editor.on('error', (e) => {
  console.warn('[lumen-editor]', e.code, e.message);
});
```

Common `e.code` values to watch for:

| Code                  | Meaning                                            |
| --------------------- | -------------------------------------------------- |
| `UPLOAD_FAILED`       | `uploadImage` threw or returned a non-string value |
| `INVALID_MIME`        | Image file failed MIME type validation             |
| `MAGIC_BYTE_MISMATCH` | File bytes do not match the declared MIME type     |
| `SIZE_EXCEEDED`       | Image exceeds the configured size limit            |

<Tip>
  Open your browser's **DevTools → Elements panel** and inspect the editor's root DOM node. Lumen renders a standard `contenteditable` `div` — you can inspect its inner HTML directly, verify that sanitization is working as expected, and confirm that your container has non-zero dimensions using the **Computed** styles tab.
</Tip>
