ruvnet/ruflo · error · Error
No models available to select task model
Error message
No models available to select task model
What it means
Thrown by resolveTaskModel when the supplied modelList is empty. resolveTaskModel picks the model used for background tasks (summaries, titles, tooling) using config.TASK_MODEL when set, otherwise models[0]. Like createValidModelIdSchema, it is called from applyModelState after the empty-list guard, so reaching it means it was called without that guard or models were cleared concurrently.
Source
Thrown at ruflo/src/ruvocal/src/lib/server/models.ts:206
added: [],
removed: [],
changed: [],
total: 0,
};
let inflightRefresh: Promise<ModelsRefreshSummary> | null = null;
const createValidModelIdSchema = (modelList: ProcessedModel[]): z.ZodType<string> => {
if (modelList.length === 0) {
throw new Error("No models available to build validation schema");
}
const ids = new Set(modelList.map((m) => m.id));
return z.string().refine((value) => ids.has(value), "Invalid model id");
};
const resolveTaskModel = (modelList: ProcessedModel[]) => {
if (modelList.length === 0) {
throw new Error("No models available to select task model");
}
if (config.TASK_MODEL) {
const preferred = modelList.find(
(m) => m.name === config.TASK_MODEL || m.id === config.TASK_MODEL
);
if (preferred) {
return preferred;
}
}
return modelList[0];
};
const signatureForModel = (model: ProcessedModel) =>
JSON.stringify({
description: model.description,
displayName: model.displayName,View on GitHub (pinned to 6b01dc5a68)
Solutions
- Only call resolveTaskModel after confirming modelList.length > 0.
- If config.TASK_MODEL references a model that is not in the list, log a warning and fall back to models[0] rather than failing - but only when the list itself is non-empty.
- Keep the applyModelState sequencing intact so this guard is exercised before resolveTaskModel.
Example fix
// before
taskModel = resolveTaskModel(models);
// after
if (models.length === 0) {
throw new Error('Cannot resolve task model: model list is empty');
}
taskModel = resolveTaskModel(models); Defensive patterns
Strategy: validation
Validate before calling
function safeResolveTaskModel(models: ProcessedModel[]) {
if (models.length === 0) throw new Error("Cannot resolve task model: empty list");
return resolveTaskModel(models);
} Type guard
function isNonEmpty<T>(list: readonly T[]): list is readonly [T, ...T[]] {
return list.length > 0;
} Try / catch
try { taskModel = resolveTaskModel(models); }
catch (e) {
if (e instanceof Error && /No models available to select task model/.test(e.message)) {
// skip task model update; keep previous value
} else throw e;
} Prevention
- Route all task-model resolution through applyModelState so the upstream empty guard fires first.
- If config.TASK_MODEL is set, validate that the id exists in the loaded list and warn if missing.
- Avoid manually resetting the global models array to [] outside of applyModelState.
When it happens
Trigger: Direct call to resolveTaskModel([]); or a code path that resets the global models array to [] and then calls refreshModels/resolveTaskModel. Normally unreachable because applyModelState checks newModels.length === 0 first (throwing error 34 instead).
Common situations: Refactor that introduces a second call site for resolveTaskModel without an empty check; test harness that stubs models as []; hot-reload clearing module state during development.
Related errors
- No models available to build validation schema
- Failed to load any models from upstream
- OPENAI_BASE_URL not set
- Failed to fetch ${baseURL}/models: ${response.status} ${resp
- Invalid completion type
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/8f68420c49d50399.
Report an issue: GitHub.