Common issues & FAQ
Solutions to frequently encountered problems when integrating FlowDrop.
Nodes don't appear in the sidebar
Symptoms: The sidebar is empty or shows "No nodes available."
Causes & fixes:
-
Endpoint config is wrong. Verify your
endpointConfigbase URL is correct and your backend is running:const endpointConfig = createEndpointConfig('http://localhost:3001/api/flowdrop');Open
http://localhost:3001/api/flowdrop/nodesin your browser — you should see JSON. -
CORS is blocking requests. Check the browser console for CORS errors. Your backend must allow the frontend's origin:
app.use(cors({ origin: 'http://localhost:5173' })); -
Node metadata is malformed. Each node needs at minimum
id,name, andtype:{ "id": "my-node", "name": "My Node", "type": "simple" } -
Response format is wrong. FlowDrop expects
{ success: true, data: [...] }, not a bare array.
Editor is blank (white screen)
Symptoms: The container is mounted but nothing renders.
Causes & fixes:
-
CSS is not imported. You must import FlowDrop styles:
import '@flowdrop/flowdrop/styles'; -
Container has no height. The editor needs a container with explicit dimensions:
#editor { width: 100%; height: 100vh; } -
Mount failed silently. Wrap in try/catch and check the console:
try { const app = await mountFlowDropApp(container, options); } catch (error) { console.error('Mount failed:', error); }
Connections won't snap
Symptoms: Dragging from an output port to an input port doesn't create a connection.
Causes & fixes:
-
Port data types are incompatible. FlowDrop enforces type-safe connections. A
triggerport cannot connect to astringport unless you define a compatibility rule. Check your port config. -
Port IDs are missing. Both source and target ports must have
idfields in the node metadata:{ "outputs": [{ "id": "output", "name": "Result", "type": "output", "dataType": "string" }] } -
No port-config endpoint. If you don't serve
/port-config, FlowDrop uses defaults which may not match your data types.
CodeMirror fields don't render
Symptoms: Config fields with format: "json" or format: "template" show as plain text inputs.
Fix: You must explicitly register CodeMirror fields against the instance's fd.fields registry. They're in a separate module to avoid the ~300KB bundle cost:
import { getInstance } from '@flowdrop/flowdrop/editor';
const fd = getInstance(); // or app.instance outside the component tree
import { registerCodeEditorField } from '@flowdrop/flowdrop/form/code';
registerCodeEditorField(fd.fields);
// For template fields with variable autocomplete:
import { registerTemplateEditorField } from '@flowdrop/flowdrop/form/code';
registerTemplateEditorField(fd.fields);
// For markdown:
import { registerMarkdownEditorField } from '@flowdrop/flowdrop/form/markdown';
registerMarkdownEditorField(fd.fields);Each installer takes the target field registry as its first argument and
re-checks registration after its dynamic import resolves, so calling it after
mount (once fd.fields is available) is the supported flow.
Multiple editors share state
Symptoms: Two FlowDrop editors on the same page appear to share workflow or history state.
Multiple editors per page are supported natively — each mount gets its own isolated FlowDropInstance. If two editors still appear to share state:
- Both mounts omitted
instanceId. The first mount without aninstanceIdbecomes the page-default instance; a second un-keyed mount can collide with it. Pass an explicitinstanceIdto each additional editor to scope its draft storage (flowdrop:draft:<instanceId>:<workflowId>), and resolve state viagetInstance()/ the mount handle's.instanceto target a specific editor. Instances are the API — there are no module-level store APIs.
Note that theme and settings (including UI toggles) are intentionally shared across all editors on a page. Registries (fd.nodes/fd.fields), the API context (fd.api), and port compatibility (fd.portCompatibility) are instance-scoped. See the multiple instances guide.
Save fails silently
Symptoms: Clicking Save does nothing visible, or changes are lost.
Causes & fixes:
-
No save endpoint. FlowDrop needs
POST /workflows(create) andPUT /workflows/:id(update) endpoints. -
No error handler. Add
onSaveErrorandonApiErrorto see what's happening:eventHandlers: { onSaveError: async (error, workflow) => { console.error('Save failed:', error); }, onApiError: (error, operation) => { console.error(`API error during ${operation}:`, error); } } -
Response format is wrong. The save endpoint must return the saved workflow with an
idfield. If creating a new workflow, the response must include the server-generated ID.
Draft recovery not working
Symptoms: Auto-saved drafts don't appear when reopening the editor.
Causes & fixes:
-
Feature is disabled. Auto-save drafts are enabled by default, but verify:
features: { autoSaveDraft: true, autoSaveDraftInterval: 30000 } -
localStorage is full. Browsers limit localStorage to ~5-10MB. Check
localStorageusage in DevTools. -
Different storage key. Drafts are keyed by workflow ID. If the workflow ID changes between sessions, the draft won't match.
Agent Spec import drops data
Symptoms: Importing an Agent Spec document loses some nodes or connections.
Cause: Not all Agent Spec features have FlowDrop equivalents. The adapter does best-effort conversion.
Fix: Check the console for warnings during import. Review the AgentSpecAdapter conversion for specific limitations.
"Cannot read properties of undefined"
Symptoms: Runtime error in the console when interacting with nodes.
Common cause: Node metadata is missing required fields. Ensure your nodes have:
{
"id": "unique-id",
"name": "Display Name",
"type": "simple",
"inputs": [],
"outputs": []
}The inputs and outputs arrays must always be present, even if empty.
Toast notifications are annoying
Fix: Disable them via features:
features: {
showToasts: false;
}Or handle errors yourself via onApiError (return true to suppress the toast for that error).
FAQ
Can I use FlowDrop without a backend?
Yes, for prototyping. Pass nodes directly and omit endpointConfig:
const app = await mountFlowDropApp(container, {
nodes: [{ id: 'my-node', name: 'My Node', type: 'simple', inputs: [], outputs: [] }]
});Saving won't work without a backend, but you can use app.getWorkflow() to extract the JSON.
Can I have multiple editors on one page?
Yes — supported natively. Each mount gets its own isolated FlowDropInstance. Pass an instanceId to each editor to scope its draft storage. Theme/settings and port config remain page-global. See the multiple instances guide.
What browsers are supported?
FlowDrop targets modern evergreen browsers (Chrome, Firefox, Safari, Edge). It requires ES2020+ support.
How do I update the node palette after mounting?
Currently, FlowDrop fetches nodes on mount. To refresh the palette, destroy and remount the editor.
Can I use FlowDrop with React/Vue/Angular?
Yes, via the Mount API. FlowDrop mounts into any HTML container element, regardless of your framework.
Getting help
If none of the above resolves your issue:
- GitHub Issues — Bug reports and reproducible problems
When reporting a bug, include:
- FlowDrop version (
npm list @flowdrop/flowdrop) - Browser and version
- The error message from the browser console
- Minimal reproduction: your node metadata JSON and mount options