liriliri/eruda · warning
Tool ${name} already exists
Error message
Tool ${name} already exists What it means
devtools.add(tool) registers a tool keyed by its `name` property in the internal `this._tools` map and creates a tab/panel for it. If a tool with the same name is already registered, the library refuses to add a duplicate and logs this warning instead, leaving the existing tool untouched. It's a guard against silent overwriting of an already-initialized tool panel.
Source
Thrown at src/DevTools/DevTools.js:111
}
toggle() {
return this._isShow ? this.hide() : this.show()
}
add(tool) {
const tab = this._tab
if (!(tool instanceof Tool)) {
const { init, show, hide, destroy } = new Tool()
defaults(tool, { init, show, hide, destroy })
}
const name = tool.name
if (!name) {
return logger.error('You must specify a name for a tool')
}
if (this._tools[name]) {
return logger.warn(`Tool ${name} already exists`)
}
const id = name.replace(/\s+/g, '-')
this._$tools.prepend(`<div id="${c(id)}" class="${c(id + ' tool')}"></div>`)
tool.init(this._$tools.find(`.${c(id)}.${c('tool')}`), this)
tool.active = false
this._tools[name] = tool
if (name === 'settings') {
tab.append({
id: name,
title: name,
})
} else {
tab.insert(tab.length - 1, {
id: name,
title: name,
})View on GitHub (pinned to 0c55928fec)
Solutions
- Check devtools.get(name) before calling add() and skip if the tool already exists.
- Call devtools.remove(name) before re-adding the tool, or use devtools.removeAll() during teardown.
- Rename your custom tool so its `name` is unique and doesn't collide with built-in tools.
- Guard the add() call so it runs only once (e.g. a module-level flag or init-once pattern) to survive HMR.
- If the duplicate add is intentional and harmless, the warning can be safely ignored — the original tool stays active.
Example fix
// before
eruda.add(myTool)
// after
if (!eruda.get('myTool')) {
eruda.add(myTool)
} Defensive patterns
Strategy: validation
Validate before calling
if (!devtools.get(tool.name)) {
devtools.add(tool)
} Type guard
function canAdd(devtools, tool) {
return tool && typeof tool.name === 'string' && tool.name.length > 0 && !devtools.get(tool.name);
} Prevention
- Always guard add() with a get(name) existence check.
- Give custom tools unique names that don't clash with built-in tool names.
- Wrap setup code in an init-once flag so HMR or double scripts don't add twice.
- Pair every add() with a remove() in teardown logic.
When it happens
Trigger: Calling devtools.add(tool) (or eruda.add(tool)) with a tool whose `name` matches a tool already added — e.g. calling add() twice with the same tool instance, adding two custom tools that share a name, re-running an init script that adds a built-in tool like 'settings' or 'elements' again, or hot module reloading re-executing the add() call without removing the old tool.
Common situations: HMR/dev-server reload re-running setup code; initializing eruda in multiple scripts or bundles that each call add(); writing a custom plugin whose name collides with a built-in tool name; accidentally passing the same tool object in a loop or an event handler that fires more than once.
Related errors
AI-assisted analysis of liriliri/eruda@0c55928fec (2026-09-01).
Data as JSON: /api/errors/7b53723c1af2cf44.
Report an issue: GitHub.