ruvnet/ruflo · error · DarwinUnavailableError
Darwin explicitly requested but unavailable
Error message
Darwin explicitly requested but unavailable
What it means
proposeFlywheelCandidates with mode 'darwin' requires a darwinInvoker function in the input. When mode is 'darwin' but input.darwinInvoker is falsy, the proposer cannot reach Darwin and, because the caller demanded Darwin (no substitution allowed), it throws DarwinUnavailableError rather than silently substituting the local proposer.
Source
Thrown at v3/@claude-flow/cli/src/services/flywheel-proposer.ts:196
}
export async function proposeFlywheelCandidates(input: ProposeCandidatesInput): Promise<CandidateArchive> {
const baselineRef = policyCandidateId(input.baselinePolicy);
const runLocal = async (substitution?: string) => finalizeArchive({
requested: input.mode,
effective: 'local',
substitution,
promotionAllowed: substitution ? input.allowSubstitutionPromotion === true : true,
baselineRef,
safetyEnvelope: input.safetyEnvelope,
seed: input.seed,
candidates: await input.localProposer(input.baselinePolicy, input.seed),
completed: true,
});
if (input.mode === 'local') return runLocal();
if (!input.darwinInvoker) {
if (input.mode === 'darwin') throw new DarwinUnavailableError('Darwin explicitly requested but unavailable');
return runLocal('darwin-unavailable');
}
try {
const maxWallTimeMs = input.maxWallTimeMs ?? 60_000;
let timeout: NodeJS.Timeout | undefined;
const result = await Promise.race([
input.darwinInvoker({
baselinePolicy: input.baselinePolicy,
seed: input.seed,
budget: {
maxEvaluationCostMicros: input.safetyEnvelope.maxEvaluationCostMicros,
maxConcurrency: input.maxConcurrency ?? 2,
maxWallTimeMs,
},
}),
new Promise<never>((_, reject) => {
timeout = setTimeout(() => reject(new DarwinUnavailableError('Darwin exceeded wall-time budget')), maxWallTimeMs);View on GitHub (pinned to 6b01dc5a68)
Solutions
- Provide a real darwinInvoker when requesting mode 'darwin'.
- If Darwin is optional, use mode 'auto' or 'local' so the proposer falls back instead of throwing.
- Gate the mode on darwinInvoker presence: mode: darwinInvoker ? 'darwin' : 'local'.
- Configure/enable the Darwin backend before requesting darwin mode.
Example fix
// before
proposeFlywheelCandidates({ mode: 'darwin', baselinePolicy, safetyEnvelope, seed, localProposer }); // throws
// after
const mode = darwinInvoker ? 'darwin' : 'local';
proposeFlywheelCandidates({ mode, darwinInvoker, baselinePolicy, safetyEnvelope, seed, localProposer }); Defensive patterns
Strategy: validation
Validate before calling
const mode = darwinInvoker ? 'darwin' : 'local';
await proposeFlywheelCandidates({ mode, darwinInvoker, baselinePolicy, safetyEnvelope, seed, localProposer }); Type guard
function hasDarwin(input: ProposeCandidatesInput): input is ProposeCandidatesInput & { darwinInvoker: NonNullable<ProposeCandidatesInput['darwinInvoker']> } {
return typeof input.darwinInvoker === 'function';
} Prevention
- Only set mode 'darwin' when darwinInvoker is wired.
- Use mode 'auto' when Darwin is optional so missing invokers fall back gracefully.
- Compute mode from invoker presence rather than hard-coding it.
- Enable/configure the Darwin backend before requesting darwin mode.
When it happens
Trigger: Calling proposeFlywheelCandidates({ mode: 'darwin', ... }) without providing darwinInvoker, or with darwinInvoker set to undefined/null because the Darwin backend is not configured in this environment.
Common situations: Darwin is gated behind a feature flag or license that is not enabled; the wiring code conditionally passes darwinInvoker only when a Darwin service URL is set, but the caller still requests mode 'darwin'; misconfiguration in a test that hard-codes mode 'darwin'.
Related errors
- Darwin archive exceeded evaluation-cost budget
- Darwin archive incomplete
- Darwin archive exceeded candidate-count budget
- Darwin failed closed: ${(error as Error).message}
- Invalid completion type
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/c9b28be89a920baa.
Report an issue: GitHub.