ruvnet/ruflo · error

No endpoints configured. This build requires…

Error message

No endpoints configured. This build requires OpenAI-compatible endpoints.

What it means

This build of chat-ui speaks exclusively to OpenAI-compatible APIs, so every processed model must carry at least one endpoint. getEndpoint() (models.ts:135), invoked lazily when a generation actually starts, throws when a model's endpoints array is missing or empty — the model was listed/selectable but cannot be served.

Solutions

  1. Add an explicit endpoint to the model entry: "endpoints": [{ "type": "openai", "baseURL": "...", "apiKey": "..." }]
  2. Or remove the broken MODELS override so models get the default OpenAI endpoint built from OPENAI_BASE_URL/OPENAI_API_KEY
  3. Validate overrides at startup (every entry has endpoints?.length > 0) and log offending model ids before users hit it
  4. If the model should not be selectable, mark it unlisted or remove it from the registry

Example fix

// before (.env)
MODELS=[{"id":"my-model","name":"My Model"}]  // getEndpoint() throws at generation time

// after
MODELS=[{
	"id":"my-model",
	"name":"My Model",
	"endpoints":[{"type":"openai","baseURL":"https://router.huggingface.co/v1"}]
}]
Defensive patterns

Strategy: validation

Validate before calling

function assertModelServable(m: { endpoints?: { type: string }[] }): void {
	if (!m.endpoints || m.endpoints.length === 0) {
		throw new Error(`Model ${String(m)} has no endpoints and cannot serve generations`);
	}
}
assertModelServable(model);
const endpoint = await model.getEndpoint();

Type guard

type ServableModel = { endpoints: { type: string }[] } & Record<string, unknown>;
function isServable(m: { endpoints?: unknown[] }): m is ServableModel {
	return Array.isArray(m.endpoints) && m.endpoints.length > 0;
}

Prevention

When it happens

Trigger: Selecting a model whose config has no endpoints: a MODELS env override entry without an "endpoints" array (or with "endpoints": []), or a model synthesized from /v1/models plus overrides such that no endpoint was attached. The throw happens on message send, not at startup.

Common situations: Hand-written MODELS JSON copied from other chat-ui forks where endpoints were optional; an override meant to tweak a model accidentally replacing its endpoints; a router returning model ids that no longer match the override shapes so endpoint attachment is skipped.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/07894dab46da43a9. Report an issue: GitHub.

Appendix: source

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

		return parts.join("\n\n");
	};
}

const processModel = async (m: ModelConfig) => ({
	...m,
	chatPromptRender: await getChatPromptRender(m),
	id: m.id || m.name,
	displayName: m.displayName || m.name,
	preprompt: m.prepromptUrl ? await fetch(m.prepromptUrl).then((r) => r.text()) : m.preprompt,
	parameters: { ...m.parameters, stop_sequences: m.parameters?.stop },
	unlisted: m.unlisted ?? false,
});

const addEndpoint = (m: Awaited<ReturnType<typeof processModel>>) => ({
	...m,
	getEndpoint: async (): Promise<Endpoint> => {
		if (!m.endpoints || m.endpoints.length === 0) {
			throw new Error("No endpoints configured. This build requires OpenAI-compatible endpoints.");
		}
		// Only support OpenAI-compatible endpoints in this build
		const endpoint = m.endpoints[0];
		if (endpoint.type !== "openai") {
			throw new Error("Only 'openai' endpoint type is supported in this build");
		}
		return await endpoints.openai({ ...endpoint, model: m });
	},
});

type InternalProcessedModel = Awaited<ReturnType<typeof addEndpoint>> & {
	isRouter: boolean;
	hasInferenceAPI: boolean;
};

const inferenceApiIds: string[] = [];

const getModelOverrides = (): ModelOverride[] => {

View on GitHub (pinned to fa13ee4ad6)