janhq/jan · error · Error
Invalid modelId: . Only alphanumeric and / _ - . characters…
Error message
Invalid modelId: ${modelId}. Only alphanumeric and / _ - . characters are allowed. What it means
The MLX extension's import() method validates the modelId before creating the model's config directory. isValidModelId rejects any id containing characters outside [A-Za-z0-9/_.-], because the id is used to build a filesystem path (providerPath/models/<modelId>/model.yml) and must not break path structure or enable path traversal.
Solutions
- Sanitize the modelId to only alphanumeric and / _ - . characters before calling import()
- Use the standard id form (e.g. 'org/repo-name' or 'org_repo') instead of a URL or path
- Trim whitespace and reject/replace illegal characters at the call site
- If importing a URL, pass it via opts.modelPath, not modelId
Example fix
// before
await mlx.import('https://huggingface.co/mlx-community/Llama-3 8B', { modelPath: '...' })
// after
await mlx.import('mlx-community/Llama-3-8B', { modelPath: '...' }) Defensive patterns
Strategy: validation
Validate before calling
const isValidModelId = (id) => typeof id === 'string' && /^[A-Za-z0-9/_.\-]+$/.test(id)
if (!isValidModelId(modelId)) throw new Error(`Invalid modelId: ${modelId}`) Type guard
const isValidModelId = (id: unknown): id is string => typeof id === 'string' && id.length > 0 && /^[A-Za-z0-9/_.\-]+$/.test(id)
Try / catch
try {
await mlx.import(modelId, opts)
} catch (e) {
if (String(e).includes('Invalid modelId')) {
throw new Error(`modelId "${modelId}" contains illegal characters; use [A-Za-z0-9/_.-] only`)
}
throw e
} Prevention
- Validate ids at the UI/API boundary before they reach import()
- Never pass URLs or file paths as modelId; use opts.modelPath for those
- Trim and normalize ids (no spaces/newlines) when copying from external sources
- Derive ids from org/repo names programmatically rather than free text
When it happens
Trigger: Calling MlxExtension.import(modelId, opts) with a modelId containing spaces, URL-encoding, query strings, backslashes, colons (e.g. 'hf.co:org/model'), '..', or any other character outside alphanumeric and / _ - . .
Common situations: Passing a full Hugging Face URL instead of an id; copying a Windows path with backslashes as the id; ids with spaces from a UI input; ids copied with trailing whitespace or newline.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Invalid argument
- Invalid input
- Failed to parse archive name
- File ' ' exceeds size limit ( bytes > MB).
- File ' ' has already been attached to this thread
AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17).
Data as JSON: /api/errors/690d78c4d54f2041.
Report an issue: GitHub.
Appendix: source
Thrown at extensions/mlx-extension/src/index.ts:607
}
const newModelConfigPath = await joinPath([newFolderPath, 'model.yml'])
await fs.mv(modelFolderPath, newFolderPath).then(() =>
invoke('write_yaml', {
data: {
...modelConfig,
model_path: modelConfig?.model_path?.replace(
`mlx/models/${modelId}`,
`mlx/models/${model.id}`
),
},
savePath: newModelConfigPath,
})
)
}
override async import(modelId: string, opts: ImportOptions): Promise<void> {
if (!isValidModelId(modelId))
throw new Error(
`Invalid modelId: ${modelId}. Only alphanumeric and / _ - . characters are allowed.`
)
const configPath = await joinPath([
await this.getProviderPath(),
'models',
modelId,
'model.yml',
])
if (await fs.existsSync(configPath))
throw new Error(`Model ${modelId} already exists`)
const sourcePath = opts.modelPath
if (sourcePath.startsWith('https://')) {
// Download from URL to mlx models folder
const janDataFolderPath = await getJanDataFolderPath()
const modelDir = await joinPath([View on GitHub (pinned to 7205d770c1)