janhq/jan · error
Jan data folder is unavailable
Error message
Jan data folder is unavailable
What it means
Thrown by the agentWorkspace helper dataFolder() when getServiceHub().app().getJanDataFolder() resolves to an empty/undefined folder path. All workspace operations (storePath, memory CRUD) depend on this base path, so the error is raised eagerly rather than writing to an invalid location.
Solutions
- Ensure the app is fully initialized before invoking workspace/memory APIs
- Check that the Jan data folder is set in app settings and points to a valid directory
- Restart the app so getJanDataFolder() re-resolves the default path
- If the setting is corrupted, reset it to the default data directory
Example fix
// before
const path = await storePath()
// after
let path: string
try {
path = await storePath()
} catch {
path = await ensureDefaultWorkspace()
} Defensive patterns
Strategy: try-catch
Validate before calling
const folder = await getServiceHub().app().getJanDataFolder()
if (!folder) throw new Error('Jan data folder is unavailable — check app settings or wait for initialization') Type guard
const hasDataFolder = (f: unknown): f is string => typeof f === 'string' && f.trim().length > 0
Try / catch
try {
await writeMemory(key, value)
} catch (e) {
if (e.message === 'Jan data folder is unavailable') {
showToast('Workspace unavailable — the app is still initializing or the data folder is unset.')
}
} Prevention
- Gate workspace features behind an 'app ready' signal
- Validate the data folder setting at startup
- Reset to a default data directory when the setting is empty
- Retry after a short delay during early startup
When it happens
Trigger: Any call to storePath, listMemories, readMemory, writeMemory, or deleteMemory while the app service returns a falsy Jan data folder — typically during early startup before the app service is ready, or when the data folder setting is unset/failed to resolve.
Common situations: Calling workspace APIs before app initialization completes; the Jan data folder configuration was cleared; the app service failed to determine the default data directory (e.g. on first launch or after a failed migration).
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- Jan data folder is unavailable
- Cannot connect to at . Please check that the service is…
- Catalog not supported for
- Critical settings "llamacpp_version" / "llamacpp_backend"…
- Current backend not found
AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17).
Data as JSON: /api/errors/0edd1e7e2aebe047.
Report an issue: GitHub.
Appendix: source
Thrown at web-app/src/lib/agentWorkspace.ts:26
import { getServiceHub } from '@/hooks/useServiceHub'
import { invalidateMemory } from '@/lib/agentTools'
import * as skillStore from '@/lib/skillStore'
import type { SkillMeta } from '@/lib/skillStore'
export type { SkillMeta }
/**
* The management surface over the agent's permanent store, for the settings UI.
* Separate from `agentTools.ts`, which is the chat-loop surface: this one edits
* what the agent remembers, that one executes what the model calls.
*
* Errors are thrown rather than swallowed. Unlike a tool call, a failed edit has
* a user waiting on it, so the page surfaces it.
*/
const dataFolder = async (): Promise<string> => {
const folder = await getServiceHub().app().getJanDataFolder()
if (!folder) throw new Error('Jan data folder is unavailable')
return folder
}
/** Path of the permanent store, created if absent. */
export async function storePath(): Promise<string> {
return await workspacePath(await dataFolder())
}
// Skill CRUD is shared with the code screen's per-project skills; only the root
// differs. These bind this page to the permanent store.
export const listSkills = () => skillStore.listSkills(skillStore.storeScope)
export const readSkill = (name: string) =>
skillStore.readSkill(skillStore.storeScope, name)
export const writeSkill = (name: string, content: string) =>
skillStore.writeSkill(skillStore.storeScope, name, content)
export const deleteSkill = (name: string) =>
skillStore.deleteSkill(skillStore.storeScope, name)
View on GitHub (pinned to 7205d770c1)