apify/crawlee · error · Error
Duplicate load signal name ${JSON.stringify(name)}: ${hint}
Error message
Duplicate load signal name ${JSON.stringify(name)}: ${hint} What it means
SystemStatus registers load signals by name and enforces uniqueness in its constructor. Passing two signals with the same name — or one shadowing a built-in signal's name — is ambiguous, so it throws with a hint explaining whether the clash is with a built-in or another custom signal.
Source
Thrown at packages/core/src/autoscaling/system_status.ts:176
/**
* Signal names are the keys of the reported {@apilink SystemInfo}, so a duplicate would leave a status object that
* contradicts actual behavior: both signals are still evaluated (any overloaded one holds concurrency down), but
* only the last is reported.
*/
private assertUniqueSignalNames(): void {
const seen = new Set<string>();
for (const { name } of this.#signals) {
if (!seen.has(name)) {
seen.add(name);
continue;
}
const hint = BUILTIN_SIGNAL_NAMES.has(name)
? `it is the name of a built-in signal. To replace that signal, switch it off with \`loadSignals: { ${BUILTIN_SIGNAL_OPTION_KEYS[name]}: false }\` and keep your implementation in \`loadSignals.custom\`; to run yours alongside it, give it a different name.`
: 'two custom signals cannot share a name - rename one of them.';
throw new Error(`Duplicate load signal name ${JSON.stringify(name)}: ${hint}`);
}
}
/**
* Returns an {@apilink SystemInfo} object with the following structure:
*
* ```javascript
* {
* isSystemIdle: Boolean,
* memInfo: Object,
* eventLoopInfo: Object,
* cpuInfo: Object
* }
* ```
*
* Where the `isSystemIdle` property is set to `false` if the system
* has been overloaded in the last `options.currentHistorySecs` seconds,
* and `true` otherwise.View on GitHub (pinned to dbe57fb09c)
Solutions
- Rename one of the duplicate custom signals.
- If the intent is to replace a built-in, disable it: `loadSignals: { <BUILTIN_KEY>: false }` and keep the implementation in `loadSignals.custom`.
- Deduplicate the array of signals before constructing SystemStatus.
Example fix
// before
new SystemStatus({ loadSignals: { custom: [{ name: 'cpu', ... }, { name: 'cpu', ... }] } });
// after
new SystemStatus({ loadSignals: { custom: [{ name: 'cpu', ... }, { name: 'gpu', ... }] } }); Defensive patterns
Strategy: validation
Validate before calling
const names = customSignals.map((s) => s.name);
const dupes = names.filter((n, i) => names.indexOf(n) !== i);
if (dupes.length) throw new Error(`Duplicate signal names: ${dupes.join(', ')}`); Try / catch
try { const status = new SystemStatus({ loadSignals: { custom: signals } }); } catch (err) { if (err.message.includes('Duplicate load signal name')) { console.error(err.message); /* follow the hint: rename or disable the built-in */ } else { throw err; } } Prevention
- Keep custom signal names distinct from built-in signal names
- Deduplicate signal arrays before constructing SystemStatus
- Read the thrown hint: built-in clashes require disabling the built-in via loadSignals
When it happens
Trigger: Passing two custom load signals with an identical `name` in `loadSignals.custom`; passing a custom signal whose name equals a built-in signal name (instead of disabling the built-in via `loadSignals: { <builtin>: false }`).
Common situations: Spreading an array of custom signals that contains duplicates; copying an example custom signal that reuses a built-in name; refactors merging two signal factories with the same default name.
Related errors
- availableMemoryRatio is not set in configuration.
- The ConcurrencySystem this AutoscaledPool borrows has not be
- Configuration is immutable. Pass options via the constructor
- The `minConcurrency`/`maxConcurrency`/`initialConcurrency`/`
- The `requestManager` option cannot be used in conjunction wi
AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30).
Data as JSON: /api/errors/c4bc526363b1a4a0.
Report an issue: GitHub.