ruvnet/ruflo · error · Error

No models available to build validation schema

Error message

No models available to build validation schema

What it means

Thrown by createValidModelIdSchema when the supplied modelList is empty. The function builds a zod schema that validates user-supplied model ids against the currently-loaded set; with no models there is nothing to validate against. In practice applyModelState guards with the same empty check before calling this, so hitting it directly indicates createValidModelIdSchema was called from somewhere that did not pre-check emptiness.

Source

Thrown at ruflo/src/ruvocal/src/lib/server/models.ts:198

export let defaultModel!: ProcessedModel;
export let taskModel!: ProcessedModel;
export let validModelIdSchema: z.ZodType<string> = z.string();
export let lastModelRefresh = new Date(0);
export let lastModelRefreshDurationMs = 0;
export let lastModelRefreshSummary: ModelsRefreshSummary = {
	refreshedAt: new Date(0),
	durationMs: 0,
	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;
		}
	}

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Ensure createValidModelIdSchema is only called after confirming models.length > 0 (applyModelState already does this).
  2. If calling it directly, pre-check the list and short-circuit or throw a more descriptive error.
  3. In tests, seed a non-empty model list before exercising the schema builder.

Example fix

// before
validModelIdSchema = createValidModelIdSchema(models); // models may be []

// after
if (models.length === 0) {
  // keep previous schema / log and skip reassignment
} else {
  validModelIdSchema = createValidModelIdSchema(models);
}
Defensive patterns

Strategy: validation

Validate before calling

function safeBuildSchema(models: ProcessedModel[]) {
  if (models.length === 0) return z.string(); // or keep previous schema
  return createValidModelIdSchema(models);
}

Type guard

function hasModels<T extends { length: number }>(list: T): list is T & { length: number } {
  return list.length > 0;
}

Try / catch

try { validModelIdSchema = createValidModelIdSchema(models); }
catch (e) {
  if (e instanceof Error && /No models available to build validation schema/.test(e.message)) {
    validModelIdSchema = z.string(); // permissive fallback during empty state
  } else throw e;
}

Prevention

When it happens

Trigger: Direct call to createValidModelIdSchema([]); or a future code path that calls it before applyModelState has populated models. During normal startup the call is sequenced after buildModels and the applyModelState guard at models.ts:245, so it should be unreachable in production.

Common situations: A fork or refactor that invokes createValidModelIdSchema independently of applyModelState; tests that exercise the schema builder in isolation without seeding models; startup race where refreshModels is called before the initial buildModels resolves.

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/a1fd45e90bbeec66. Report an issue: GitHub.