ruvnet/ruflo · error
Invalid completion type
Error message
Invalid completion type
What it means
endpointOai() implements exactly two completion modes: "completions" (legacy /v1/completions) and "chat_completions" (/v1/chat/completions). After handling both, any other runtime value falls into the final else and throws "Invalid completion type" (endpointOai.ts:264). The zod schema (union of the two literals, default "chat_completions") normally rejects bad values earlier with a ZodError, so reaching this throw means a loosely-typed path bypassed or pre-parsed the schema.
Solutions
- Set completion to "chat_completions" (or omit it — that is the default) for chat models
- Use "completions" only for raw text-completion models behind /v1/completions
- Validate any override against endpointOAIParametersSchema.parse(...) before passing it to endpointOai so bad enum values fail fast with a ZodError naming the field
- Search your MODELS env / config files for stale completion names
Example fix
// before
const endpoint = await endpoints.openai({ ...cfg, completion: "legacy_completions" }); // Invalid completion type
// after
const endpoint = await endpoints.openai({
...cfg,
completion: "chat_completions", // or "completions" for raw /v1/completions models
}); Defensive patterns
Strategy: validation
Validate before calling
const COMPLETION_TYPES = ["completions", "chat_completions"] as const;
if (!COMPLETION_TYPES.includes(cfg.completion)) {
throw new Error(`completion must be one of ${COMPLETION_TYPES.join(" | ")}`);
} Type guard
type CompletionType = "completions" | "chat_completions";
function isValidCompletion(v: unknown): v is CompletionType {
return v === "completions" || v === "chat_completions";
} Prevention
- Always parse endpoint params through endpointOAIParametersSchema.parse so bad enum values fail with a field-level ZodError at config load, not at generation time
- Validate MODELS JSON overrides against the schema in a startup check
- Search configs for stale names like legacy_completions when porting from other forks
When it happens
Trigger: Constructing an endpoint with completion set to "legacy_completions" (old chat-ui naming), "assistant", "text_completions", or any arbitrary string — typically via a MODELS env override parsed as JSON5 and cast to any, or code that builds endpoint params from a pre-parsed object without schema.parse.
Common situations: Porting model configs from upstream huggingface/chat-ui forks that used different completion names; hand-writing the MODELS JSON override with a remembered-but-wrong value; a custom router/alias path constructing endpoints from raw config objects.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- HTTP transport requires host and port configuration
- INVALID_API_KEY_LENGTH
- Invalid CLAUDE_FLOW_ENCRYPTION_KEY: expected 32-byte key as…
- Invalid GCS bucket name
- Invalid inputDim: . Must be positive.
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/19dccd9e9a8e50db.
Report an issue: GitHub.
Appendix: source
Thrown at ruflo/src/ruvocal/src/lib/server/endpoints/openai/endpointOai.ts:264
{
body: { ...body, ...extraBody },
headers: {
"ChatUI-Conversation-ID": conversationId?.toString() ?? "",
"X-use-cache": "false",
...(locals?.token ? { Authorization: `Bearer ${locals.token}` } : {}),
// Bill to organization if configured
...(locals?.billingOrganization
? { "X-HF-Bill-To": locals.billingOrganization }
: {}),
},
signal: abortSignal,
}
);
return openAIChatToTextGenerationSingle(openChatAICompletion, () => routerMetadata);
}
};
} else {
throw new Error("Invalid completion type");
}
}
View on GitHub (pinned to fa13ee4ad6)