{"record":{"id":"10b49289fc7f1bbf","repo":"janhq/jan","slug":"servicehub-not-initialized-or-model-provider-missi","errorCode":null,"errorMessage":"ServiceHub not initialized or model/provider missing.","messagePattern":"ServiceHub not initialized or model/provider missing\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web-app/src/lib/custom-chat-transport.ts","lineNumber":1123,"sourceCode":"      messages: UIMessage[]\n      abortSignal: AbortSignal | undefined\n    } & {\n      trigger: 'submit-message' | 'regenerate-message'\n      messageId: string | undefined\n    } & ChatRequestOptions\n  ): Promise<ReadableStream<UIMessageChunk>> {\n    const threadId = this.threadId ?? options.chatId\n    const myGeneration = ++this.streamGeneration\n    useAppState.getState().setCurrentStreamThreadId(threadId)\n    // Capture the effective provider name early so the Anthropic serial\n    // tool-use repair later uses the same value that was used to create the\n    // model, even if the user switches provider mid-request.\n    const modelId = useModelProvider.getState().selectedModel?.id\n    const providerId = useModelProvider.getState().selectedProvider\n    const effectiveProviderName = providerId\n    const provider = useModelProvider.getState().getProviderByName(providerId)\n    if (!this.serviceHub || !modelId || !provider) {\n      throw new Error('ServiceHub not initialized or model/provider missing.')\n    }\n\n    this.lastUserMessage = extractLatestUserText(options.messages)\n\n    try {\n      const updatedProvider = useModelProvider\n        .getState()\n        .getProviderByName(providerId)\n\n      const inferenceParams = this.getActiveInferenceParams()\n\n      const selectedModel = useModelProvider.getState().selectedModel\n      const reasoningParams = buildLlamacppReasoningParams(\n        effectiveProviderName,\n        selectedModel?.settings?.reasoning?.controller_props?.value as\n          | 'auto'\n          | 'on'\n          | 'off'","sourceCodeStart":1105,"sourceCodeEnd":1141,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/web-app/src/lib/custom-chat-transport.ts#L1105-L1141","documentation":"Thrown at the very start of `sendMessages` when any of three preconditions is falsy: `this.serviceHub`, the selected model id (`useModelProvider.getState().selectedModel?.id`), or the resolved provider (`getProviderByName(providerId)`). It is a hard precondition gate before any model creation or streaming begins.","triggerScenarios":"Sending a message before ServiceHub finished initializing; `selectedProvider` points to a provider name that no longer exists in the store (deleted/renamed); no model selected (`selectedModel` is null); providerId is undefined because the provider store was reset.","commonSituations":"Race where the user sends a message during app startup before ServiceHub is injected; the selected provider was removed by the user but the selected-provider pointer wasn't cleared; migrating provider configs left a dangling reference; first-run with no provider configured.","solutions":["Ensure a provider and model are selected before enabling the send button.","Verify ServiceHub is initialized (await its ready signal) before sendMessages can fire.","Clear `selectedProvider` when a provider is deleted so the UI falls back to a valid one.","Show a setup prompt instead of letting the send path run."],"exampleFix":"// before\nconst provider = useModelProvider.getState().getProviderByName(providerId)\nif (!this.serviceHub || !modelId || !provider) {\n  throw new Error('ServiceHub not initialized or model/provider missing.')\n}\n\n// after\nconst provider = useModelProvider.getState().getProviderByName(providerId)\nif (!this.serviceHub) {\n  throw new Error('ServiceHub not initialized yet. Wait for startup to finish.')\n}\nif (!provider || !modelId) {\n  throw new Error('No model or provider selected. Choose one before sending.')\n}","handlingStrategy":"validation","validationCode":"const { selectedModel, selectedProvider } = useModelProvider.getState()\nconst provider = useModelProvider.getState().getProviderByName(selectedProvider)\nif (!this.serviceHub) {\n  toast.error('App still starting up', { description: 'Try again in a moment.' })\n  return\n}\nif (!selectedModel?.id || !provider) {\n  toast.error('No model selected', { description: 'Choose a provider and model first.' })\n  return\n}","typeGuard":"function hasSendPreconditions(hub: unknown, modelId: unknown, provider: unknown): boolean {\n  return !!hub && typeof modelId === 'string' && modelId.length > 0 && !!provider && typeof (provider as any).base_url === 'string'\n}","tryCatchPattern":"try {\n  if (!hasSendPreconditions(this.serviceHub, modelId, provider)) {\n    toast.error('Cannot send message', { description: 'ServiceHub, model, or provider not ready.' })\n    return\n  }\n  // proceed\n} catch (error) {\n  console.error('sendMessages precondition failure:', error)\n  throw error\n}","preventionTips":["Disable the send button until a provider + model are selected and ServiceHub is ready.","Clear selectedProvider when its provider is deleted.","Await ServiceHub initialization before allowing sends.","Show a first-run setup flow so these are never null."],"tags":["transport","provider","initialization","state"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}