Skip to content

Troubleshooting & FAQ

Use this checklist when something feels off. Most responses link back to other chapters for deeper fixes.

Web component isn’t defined

Symptom: The console shows customElements.define… already used or sciflow-editor is not defined.

Fixes:

  1. Import the bundle only once per page. When using bundlers, prefer a single entry point that re-exports @sciflow/editor-start.
  2. If you hot-reload modules, guard the definition:
    if (!customElements.get('sciflow-editor')) {
      await import('@sciflow/editor-start');
    }
    

Duplicate definitions

Loading the bundle twice on the same page throws NotSupportedError. Ensure that both the demo bundle and your application bundle aren’t included together.

Toolbar icons are blank squares

As of the current release, toolbar icons are bundled as inline SVGs and no external font is required. If you see blank squares, you may be using an older version of @sciflow/editor-start that relied on the Google Fonts CDN. Upgrade to the latest version, which includes all icons in the bundle. See Icons for details.

Paste turns everything into citations

The citation feature only converts clipboard payloads marked with application/x-sciflow-reference. If you see unexpected conversions:

  1. Confirm that your clipboard handler isn’t injecting JSON with { type: 'reference' }.
  2. Update to the latest bundle where paste detection ignores plain text that isn’t tagged as a reference (fix merged via extractDropPayload hardening).

Outline clicks don’t scroll the editor

Call commands.focus() before commands.scrollIntoView() (already built into the custom outline recipe). Focus ensures that browsers actually honor the scroll request.

Equations show as placeholder or raw TeX

Symptom: Math nodes display a placeholder message or raw TeX instead of rendered SVG.

Fix: The math feature is enabled by default, but the host page must load MathJax 4 for equations to render. Add this script tag to your HTML (typically in <head>):

<script defer src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-svg.js"></script>

Without it, equations still save and load correctly; only the visual rendering is deferred.

Registry returns 404

@sciflow/editor-start, @sciflow/editor-core, @sciflow/schema-prosemirror, @sciflow/schema-core, @sciflow/pandoc-ast and @sciflow/pandoc-web resolve on the public npm registry and need no registry configuration. If one of them 404s, check that no .npmrc in the project, your home directory, or NPM_CONFIG_USERCONFIG is redirecting the @sciflow scope elsewhere.

@sciflow/reader is not on the public registry, so a 404 for that one is expected rather than a misconfiguration. See Getting Started.

The first import is slow and downloads ~58 MB

Symptom: The first DOCX / Markdown / LaTeX import takes far longer than later ones, and the network panel shows a large pandoc.wasm request.

Cause: This is by design. @sciflow/pandoc-web runs Pandoc in the browser, and the Pandoc binary is ~58 MB uncompressed. It is fetched lazily on the first conversion — never on page load — and then reused for the rest of the page's lifetime.

Fixes:

  1. Show a loading state. <sciflow-pandoc-drop> renders one by default and emits sciflow-status; if you drive convertFile() yourself, put up your own indicator before awaiting it.
  2. Compress the asset. With gzip the transfer is ~16 MB, with brotli ~11 MB. Make sure your server or CDN compresses application/wasm; many default configurations do not.
  3. Cache it properly. Vite, Webpack and Rspack emit pandoc.wasm with a content hash, so it is safe to serve with a long Cache-Control: max-age. Without one, every page load pays the download again.
  4. Warm it early if you can. When you know an import is coming (the user opened an import screen), call loadPandoc() and ignore the result. The instance is memoized, so the real conversion reuses it.

Later conversions on the same page cost nothing extra — only the first one pays.

See Importing documents for the full size and caching notes.

WASM fetch fails with 404 after bundling

Symptom: Import works in development but breaks in a production build. The console shows a 404 for pandoc.wasm, or a WASM error such as CompileError: … magic word / expected magic word 00 61 73 6d — that second form is the WASM compiler being handed the HTML body of a 404 page.

Cause: The binary was not emitted next to your bundle. @sciflow/pandoc-web depends on pandoc-wasm like any other package and imports it through its package entry point, which asks the bundler for the URL of pandoc.wasm — but only a bundler configured to treat .wasm as an asset to copy, rather than as a module to parse or a dependency to pre-bundle, will hand back a URL that resolves.

Fixes:

  1. Confirm the file exists in your build output (dist/assets/pandoc-*.wasm or equivalent) and that requesting its URL returns Content-Type: application/wasm, not HTML.
  2. Vite: emit the binary from a pre plugin, keep .wasm in assetsInclude alongside it, and keep the dependency out of pre-bundling, which rewrites the asset URL out from under the engine — the full config is in Bundling. A build that stops on an unresolved wasi_snapshot_preview1 rather than 404ing is that plugin missing: Vite is compiling the binary as a module instead of copying it.
  3. Webpack 5 / Rspack: if you have a custom module.rules entry matching .wasm, make sure this file falls under type: 'asset/resource'. A WASM loader that tries to instantiate it will fail on its WASI imports (wasi_snapshot_preview1).
  4. Check that the pandoc-wasm dependency actually installed its .wasm binary. It is a ~58 MB file, and installs that skip large artifacts (an aggressive or partial CI cache) can leave it missing while everything else resolves.
  5. If you serve the bundle from a CDN on a different origin, the WASM request follows the same CORS rules as any other asset — see CORS errors above.

Because loadPandoc() memoizes its promise, a failed load stays failed for the life of the page: reload after fixing the deployment.

Content security policy blocks styles or scripts

Symptom: The editor renders but looks unstyled, or the console shows CSP violations like Refused to apply inline style.

Fixes:

  1. style-src 'unsafe-inline' is required. The editor's own component styles use constructed stylesheets, but two paths create ordinary inline <style> elements, and no API exists to put a nonce on either of them:

    • Editor content styles are injected once into document.head as <style data-sf-content-styles> when the first editor instance connects (the editable surface lives in the light DOM, which a shadow-root stylesheet cannot reach).
    • Consumer overrides passed to shadowStyles / setShadowStyles() are appended as <style> elements inside the shadow root.

    Both are blocked by a style-src that lists only origins or a nonce, and the symptom is exactly the unstyled editor above. There is no nonce-only configuration for this release. 2. If you load MathJax from a CDN, add cdn.jsdelivr.net to script-src. 3. For WebSocket sync, add your sync server to connect-src.

See Browser Compatibility for the full directive list.

CORS errors when loading images or syncing

Symptom: Images don't load, or the sync connection fails with Access-Control-Allow-Origin errors.

Fixes:

  1. Configure your image server or CDN to return Access-Control-Allow-Origin for your application's origin.
  2. For WebSocket connections (Yjs sync), the WebSocket server must accept connections from your origin.
  3. If serving the editor bundle from a different domain, ensure CORS headers are set on that domain too.

Tables look broken or can't be edited

Symptom: Table cells aren't selectable, columns can't be resized, or table markup appears instead of a rendered table.

Fixes:

  1. Ensure the table feature is included in your feature set. If you use a custom features array, add the table feature explicitly.
  2. Table CSS is part of sciflow-editor.css. Verify the stylesheet is loaded.
  3. Column resizing requires pointer events — if you have pointer-events: none on a parent container, it will break table interactions.

ProseMirror devtools integration

For debugging document state, install the ProseMirror DevTools browser extension. Access the ProseMirror view for debugging:

const editor = document.getElementById('editor');
// Access the underlying ProseMirror EditorView
const view = editor.editorView;
console.log('Current doc:', view.state.doc.toJSON());
console.log('Selection:', view.state.selection.toJSON());

Debug logging

SciFlow logs errors to the console prefixed with [sciflow-editor]:

Message Cause
failed to initialize editor Initialization failure — check for duplicate custom element definitions
dropping invalid link node A cross-reference node has a malformed href or missing target
unable to read supplied CSSStyleSheet Shadow style injection failed — check that your CSS is valid
received invalid doc JSON; falling back to default document The doc property was set to invalid JSON

To inspect plugin state programmatically:

import { PluginKey } from 'prosemirror-state';

const key = new PluginKey('my-plugin');
const state = editor.plugins.getState(key);
console.log('Plugin state:', state);

Collaborative cursors not showing

Symptom: Multiple users are editing but remote cursors or selections are invisible.

Fixes:

  1. Ensure you're using the Yjs sync adapter with awareness enabled on your YjsProvider.
  2. Remote cursor styles require the editor's default CSS. If you override Shadow DOM styles, verify the cursor classes (.yjs-cursor, .yjs-selection) aren't hidden.
  3. Check that the WebSocket connection is active — cursors rely on Yjs Awareness, which needs a live connection.

Schema validation errors on load

Symptom: The editor loads a default empty document instead of your content, with a console error about invalid JSON.

Fixes:

  1. Validate your document JSON against the generated schema:
    npx nx run @sciflow/schema-prosemirror:generate-schema
    
    Then compare your JSON against manuscript-snapshot.schema.json.
  2. Common causes: missing required type fields on nodes, invalid attribute values, content that doesn't match the node's content expression.
  3. After schema updates, existing documents may need migration. See Content Import & Export.

Need help?

  1. Review the User Guide sections again.
  2. Check the Developer Guide if you suspect a build issue.
  3. See Browser Compatibility for environment-specific issues.
  4. Still stuck? Capture logs/screenshots and share them with the core team.