ruvnet/ruflo · critical
No models available to select task model
Error message
No models available to select task model
What it means
Thrown by resolveTaskModel in the server model registry (ruflo/src/ruvocal/src/lib/server/models.ts). The chat UI derives a 'task model' (used for background/title-generation tasks) from the processed model list fetched from OPENAI_BASE_URL/models; an empty list is unrecoverable because the function must return a concrete ProcessedModel. In practice applyModelState guards emptiness first, so this fires when resolveTaskModel is called directly with an empty registry (e.g., startup before the first successful refresh).
Solutions
- Fix the root cause upstream first: curl ${OPENAI_BASE_URL}/models with the same OPENAI_API_KEY and confirm it returns a non-empty data array.
- If the first refresh failed, address that error (see 'Failed to fetch ...' / 'OPENAI_BASE_URL not set') so the registry populates and resolveTaskModel gets a non-empty list.
- Guard call sites: only invoke taskModel after a successful refresh (check models.length > 0 or lastModelRefresh > epoch).
- If TASK_MODEL is set, verify it matches a model id or name returned by upstream, otherwise it silently falls back to models[0] once the list is non-empty.
Example fix
// before
const tm = resolveTaskModel(models); // throws when registry empty
// after
if (models.length === 0) {
throw new Error("Model registry is empty; wait for the initial refresh to succeed");
}
const tm = resolveTaskModel(models); Defensive patterns
Strategy: validation
Validate before calling
// before touching the registry
import { models, lastModelRefresh } from "$lib/server/models";
if (models.length === 0 || lastModelRefresh.getTime() === 0) {
throw new Error("Model registry not populated yet; wait for initial refresh");
} Type guard
function hasModels<T>(list: T[]): list is [T, ...T[]] {
return list.length > 0;
} Prevention
- Treat an empty upstream model list as a deployment blocker and fail startup loudly.
- Expose readiness from the model-refresh summary (lastModelRefreshSummary.total > 0) and gate traffic on it.
- Monitor the periodic refresh; alert when it throws so the registry never silently stays empty.
When it happens
Trigger: Calling resolveTaskModel([]) or any code path that reaches it while the global `models` array is still empty: server booted but the initial buildModels() fetch has not completed or failed; upstream /models returned an empty array; or a test/helper invokes the function on an empty list.
Common situations: Self-hosted deployments where OPENAI_BASE_URL points at a gateway that returns an empty `data` array; startup race where a request needing taskModel arrives before the first model refresh; TASK_MODEL env var set but the registry never populated because the upstream fetch failed.
Related errors
- OPENAI_BASE_URL not set
- Failed to load any models from upstream
- INTERNAL_ERROR
- No endpoints configured. This build requires…
- No models available to build validation schema
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/8f68420c49d50399.
Report an issue: GitHub.
Appendix: 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 fa13ee4ad6)