{"record":{"id":"19dccd9e9a8e50db","repo":"ruvnet/ruflo","slug":"invalid-completion-type","errorCode":null,"errorMessage":"Invalid completion type","messagePattern":"Invalid completion type","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ruflo/src/ruvocal/src/lib/server/endpoints/openai/endpointOai.ts","lineNumber":264,"sourceCode":"\t\t\t\t\t{\n\t\t\t\t\t\tbody: { ...body, ...extraBody },\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"ChatUI-Conversation-ID\": conversationId?.toString() ?? \"\",\n\t\t\t\t\t\t\t\"X-use-cache\": \"false\",\n\t\t\t\t\t\t\t...(locals?.token ? { Authorization: `Bearer ${locals.token}` } : {}),\n\t\t\t\t\t\t\t// Bill to organization if configured\n\t\t\t\t\t\t\t...(locals?.billingOrganization\n\t\t\t\t\t\t\t\t? { \"X-HF-Bill-To\": locals.billingOrganization }\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsignal: abortSignal,\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\treturn openAIChatToTextGenerationSingle(openChatAICompletion, () => routerMetadata);\n\t\t\t}\n\t\t};\n\t} else {\n\t\tthrow new Error(\"Invalid completion type\");\n\t}\n}\n","sourceCodeStart":246,"sourceCodeEnd":267,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/ruflo/src/ruvocal/src/lib/server/endpoints/openai/endpointOai.ts#L246-L267","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst endpoint = await endpoints.openai({ ...cfg, completion: \"legacy_completions\" }); // Invalid completion type\n\n// after\nconst endpoint = await endpoints.openai({\n\t...cfg,\n\tcompletion: \"chat_completions\", // or \"completions\" for raw /v1/completions models\n});","handlingStrategy":"validation","validationCode":"const COMPLETION_TYPES = [\"completions\", \"chat_completions\"] as const;\nif (!COMPLETION_TYPES.includes(cfg.completion)) {\n\tthrow new Error(`completion must be one of ${COMPLETION_TYPES.join(\" | \")}`);\n}","typeGuard":"type CompletionType = \"completions\" | \"chat_completions\";\nfunction isValidCompletion(v: unknown): v is CompletionType {\n\treturn v === \"completions\" || v === \"chat_completions\";\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["openai","endpoint","enum","validation","configuration"],"backgroundTag":"invalid-enum-value","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}