ruvnet/ruflo · error
Daemon '${name}' is disabled
Error message
Daemon '${name}' is disabled What it means
DaemonManager.start(name) throws this when the daemon exists and is not running, but its registered config has enabled: false. Disabled daemons refuse to start as a deliberate control — you must explicitly re-enable via manager.enable(name) (or register with enabled: true) before starting.
Source
Thrown at v3/@claude-flow/hooks/src/daemons/index.ts:83
this.daemons.set(config.name, { config, state, task });
}
/**
* Start a daemon
*/
async start(name: string): Promise<void> {
const daemon = this.daemons.get(name);
if (!daemon) {
throw new Error(`Daemon '${name}' not found`);
}
if (daemon.state.status === 'running') {
return; // Already running
}
if (!daemon.config.enabled) {
throw new Error(`Daemon '${name}' is disabled`);
}
daemon.state.status = 'starting';
daemon.state.startedAt = new Date();
try {
// Start interval timer
daemon.timer = setInterval(async () => {
await this.executeDaemonTask(name);
}, daemon.config.interval);
daemon.state.status = 'running';
daemon.state.pid = process.pid; // Use current process for in-process daemons
// Run initial execution
await this.executeDaemonTask(name);
} catch (error) {
daemon.state.status = 'error';View on GitHub (pinned to fa13ee4ad6)
Solutions
- Call manager.enable(name) before manager.start(name) for daemons registered disabled
- Or register with enabled: true if the daemon should start with the manager
- Centralize the enable+start sequence in one startDaemon(name) helper so they cannot diverge
Example fix
// before
manager.register({ name: 'metrics', interval: 60_000, enabled: false }, task);
await manager.start('metrics'); // throws: disabled
// after
manager.enable('metrics');
await manager.start('metrics'); Defensive patterns
Strategy: validation
Validate before calling
// Explicit enable+start keeps intent clear
function startDaemon(manager: DaemonManager, name: string): Promise<void> {
if (manager.getState(name) === undefined) {
throw new Error(`daemon '${name}' not registered`);
}
manager.enable(name); // no-op style guard before start
return manager.start(name);
} Try / catch
try {
await manager.start(name);
} catch (e) {
if (e instanceof Error && e.message.includes('is disabled')) {
manager.enable(name);
await manager.start(name);
return;
}
throw e;
} Prevention
- Default enabled: true in registration configs unless the daemon is deliberately opt-in
- Gate opt-in daemons on a feature flag that drives enable() — not just start()
- Log daemon states (getAllStates) at startup to spot disabled daemons early
When it happens
Trigger: Registering a daemon with { name, interval, enabled: false } (e.g. an opt-in daemon) and later calling start(name) without calling enable(name) first; or calling disable(name) at runtime and then start(name) again.
Common situations: Daemons registered disabled-by-default for feature-flag rollout where the flag flips but enable() is never invoked; shutdown logic that disables daemons and restart logic that only calls start(); config-driven enabled fields defaulting to false when omitted from partial config objects.
Related errors
- Daemon '${config.name}' is already registered
- Daemon '${name}' not found
- Can only resume paused agent
- SSRF guard: invalid URL — ${rawUrl}
- SSRF guard: invalid URL — ${rawUrl}
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/dfdfd2d0b94af09f.
Report an issue: GitHub.