ruvnet/ruflo · error · DarwinUnavailableError
Darwin failed closed: ${(error as Error).message}
Error message
Darwin failed closed: ${(error as Error).message} What it means
If the darwinInvoker throws something other than DarwinUnavailableError, the catch block wraps the original message as DarwinUnavailableError('Darwin failed closed: <original>'). In mode 'darwin' this rethrows (the caller demanded Darwin and must see the failure); in other modes it would fall back to the local proposer with a 'darwin-error:...' substitution. 'Failed closed' signals an unexpected Darwin-side fault that the proposer will not silently mask.
Source
Thrown at v3/@claude-flow/cli/src/services/flywheel-proposer.ts:247
0,
);
if (evaluationCost > input.safetyEnvelope.maxEvaluationCostMicros) {
throw new DarwinUnavailableError('Darwin archive exceeded evaluation-cost budget');
}
return finalizeArchive({
requested: input.mode,
effective: 'darwin',
promotionAllowed: true,
baselineRef,
safetyEnvelope: input.safetyEnvelope,
seed: input.seed,
candidates: result.candidates,
completed: true,
});
} catch (error) {
if (input.mode === 'darwin') {
if (error instanceof DarwinUnavailableError) throw error;
throw new DarwinUnavailableError(`Darwin failed closed: ${(error as Error).message}`);
}
return runLocal(`darwin-error:${(error as Error).message}`);
}
}
View on GitHub (pinned to 6b01dc5a68)
Solutions
- Read the wrapped message: the original error's text is preserved after 'Darwin failed closed:'.
- Stabilize the Darwin backend (network, service health) and retry.
- If Darwin is unreliable, run with mode 'auto' so failures fall back to local instead of surfacing.
- Harden the darwinInvoker to translate known transient errors into retries or DarwinUnavailableError with a clear reason.
Example fix
// before
try { await proposeFlywheelCandidates({ mode: 'darwin', darwinInvoker, ... }); }
catch (e) { /* 'Darwin failed closed: <x>' — surface to user */ }
// after — fall back when Darwin is flaky
const archive = await proposeFlywheelCandidates({ mode: 'auto', darwinInvoker, ... });
// archive.effective === 'local', archive.substitution === 'darwin-error:<x>' on failure Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate by health-checking Darwin before the run:
if (darwinInvoker && !(await isDarwinHealthy(darwinInvoker))) {
// run local instead, or surface a clear message
await proposeFlywheelCandidates({ mode: 'local', ... });
} else {
await proposeFlywheelCandidates({ mode: 'darwin', darwinInvoker, ... });
} Try / catch
try {
return await proposeFlywheelCandidates({ mode: 'darwin', darwinInvoker, ... });
} catch (e) {
if (e instanceof DarwinUnavailableError) {
// original cause is in the message after 'Darwin failed closed:'
return await proposeFlywheelCandidates({ mode: 'local', ... });
}
throw e;
} Prevention
- Use mode 'auto' so unexpected Darwin errors fall back to local.
- Health-check Darwin (network/service) before requesting mode 'darwin'.
- Read the wrapped original message to diagnose the underlying fault.
- Harden the darwinInvoker to translate transient errors into retries or clear reasons.
When it happens
Trigger: The darwinInvoker rejects with an arbitrary error (network failure, serialization error, unhandled exception inside Darwin, timeout from a non-budget source) that is not already a DarwinUnavailableError.
Common situations: Darwin service is unreachable (DNS/connection refused); Darwin threw a TypeError/RangeError internally; the invoker's response failed schema parsing; an upstream dependency of Darwin crashed.
Related errors
- Darwin explicitly requested but unavailable
- Darwin archive incomplete
- Darwin archive exceeded candidate-count budget
- Darwin archive exceeded evaluation-cost budget
- Invalid completion type
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/6d6a6a7d4ebc12fc.
Report an issue: GitHub.