janhq/jan · warning · Error
Conversational extension not available yet
Error message
Conversational extension not available yet
What it means
Thrown by DefaultThreadsService.fetchThreads when ExtensionManager.get<ConversationalExtension>(ExtensionTypeEnum.Conversational) returns undefined. By design it signals a transient startup race (e.g., a reload while the llamacpp router is still initializing) so the caller retries instead of treating 'not ready' as 'no threads' and wiping the cached list.
Source
Thrown at web-app/src/services/threads/default.ts:33
assistantModel: { id: string; engine?: string } | undefined,
fallback?: Thread['model']
): Thread['model'] | undefined {
if (assistantModel) {
return { id: assistantModel.id, provider: assistantModel.engine ?? 'llamacpp' }
}
return fallback
}
export class DefaultThreadsService implements ThreadsService {
async fetchThreads(): Promise<Thread[]> {
const ext = ExtensionManager.getInstance().get<ConversationalExtension>(
ExtensionTypeEnum.Conversational
)
// The extension may not be registered yet during a startup race (e.g. a
// reload while the llamacpp router is busy). Throw so the caller can retry
// instead of treating "not ready" as "no threads" and wiping the list.
if (!ext) {
throw new Error('Conversational extension not available yet')
}
// Let listThreads failures propagate: a rejected invoke means "backend not
// ready / errored", not "no threads" — the caller retries instead of
// wiping the list with [].
const threads = await ext.listThreads()
if (!Array.isArray(threads)) return []
// new String("id") !== "id"
threads.forEach((e) => {
e.id = e.id?.toString()
e.assistants?.forEach((a) => {
a.id = a.id?.toString()
if (a.model) a.model.id = a.model.id?.toString()
})
})
// Filter out temporary threads from the listView on GitHub (pinned to fad3f12a14)
Solutions
- Retry fetchThreads after a short backoff - the extension usually registers within a few hundred ms of startup.
- Check the extension manager logs to confirm the Conversational extension loaded successfully.
- If it persists, verify the conversational extension is packaged and enabled for this build.
Example fix
// before: a single call on a cold start wipes the thread list
const threads = await threadsService.fetchThreads()
// after: retry specifically on the 'not available yet' signal
async function loadThreads(maxAttempts = 5) {
for (let i = 0; i < maxAttempts; i++) {
try { return await threadsService.fetchThreads() }
catch (e) {
if (e instanceof Error && e.message.includes('not available yet') && i < maxAttempts - 1) {
await new Promise(r => setTimeout(r, 300 * (i + 1))); continue
}
throw e
}
}
} Defensive patterns
Strategy: retry
Validate before calling
function isConversationalReady(): boolean {
return !!ExtensionManager.getInstance().get(ExtensionTypeEnum.Conversational)
} Type guard
function isExtensionNotReadyError(e: unknown): boolean {
return e instanceof Error && e.message.includes('not available yet')
} Try / catch
for (let i = 0; i < 5; i++) {
try { setThreads(await threadsService.fetchThreads()); break }
catch (e) {
if (isExtensionNotReadyError(e) && i < 4) {
await new Promise(r => setTimeout(r, 300 * (i + 1))); continue
}
throw e
}
} Prevention
- Treat this specific message as retryable; never clear cached thread lists on it.
- Gate initial thread load behind an 'extensions ready' signal if one exists.
When it happens
Trigger: The Conversational extension is not registered yet at the moment of the call - get() returns undefined. Happens during cold start, during a reload while another router is busy, or when the extension failed/was disabled.
Common situations: App cold start before extensions finish registering; reload during model loading; the conversational extension crashed on init; a build that excluded the conversational extension.
Related errors
- Vector DB extension does not support project-level ingestion
- Vector DB extension not available
- llamacpp extension not available
- llamacpp extension not available
- MLX engine not found
AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12).
Data as JSON: /api/errors/3fd26f99de1bc6f8.
Report an issue: GitHub.