{"record":{"id":"690d78c4d54f2041","repo":"janhq/jan","slug":"invalid-modelid-modelid-only-alphanumeric-and-690d78","errorCode":null,"errorMessage":"Invalid modelId: ${modelId}. Only alphanumeric and / _ - . characters are allowed.","messagePattern":"Invalid modelId: (.+?)\\. Only alphanumeric and / _ - \\. characters are allowed\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"extensions/mlx-extension/src/index.ts","lineNumber":607,"sourceCode":"    }\n    const newModelConfigPath = await joinPath([newFolderPath, 'model.yml'])\n    await fs.mv(modelFolderPath, newFolderPath).then(() =>\n      invoke('write_yaml', {\n        data: {\n          ...modelConfig,\n          model_path: modelConfig?.model_path?.replace(\n            `mlx/models/${modelId}`,\n            `mlx/models/${model.id}`\n          ),\n        },\n        savePath: newModelConfigPath,\n      })\n    )\n  }\n\n  override async import(modelId: string, opts: ImportOptions): Promise<void> {\n    if (!isValidModelId(modelId))\n      throw new Error(\n        `Invalid modelId: ${modelId}. Only alphanumeric and / _ - . characters are allowed.`\n      )\n\n    const configPath = await joinPath([\n      await this.getProviderPath(),\n      'models',\n      modelId,\n      'model.yml',\n    ])\n    if (await fs.existsSync(configPath))\n      throw new Error(`Model ${modelId} already exists`)\n\n    const sourcePath = opts.modelPath\n\n    if (sourcePath.startsWith('https://')) {\n      // Download from URL to mlx models folder\n      const janDataFolderPath = await getJanDataFolderPath()\n      const modelDir = await joinPath([","sourceCodeStart":589,"sourceCodeEnd":625,"githubUrl":"https://github.com/janhq/jan/blob/7205d770c1e097c3daf35a911176410e93bc5564/extensions/mlx-extension/src/index.ts#L589-L625","documentation":"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.","triggerScenarios":"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 / _ - . .","commonSituations":"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.","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"],"exampleFix":"// before\nawait mlx.import('https://huggingface.co/mlx-community/Llama-3 8B', { modelPath: '...' })\n// after\nawait mlx.import('mlx-community/Llama-3-8B', { modelPath: '...' })","handlingStrategy":"validation","validationCode":"const isValidModelId = (id) => typeof id === 'string' && /^[A-Za-z0-9/_.\\-]+$/.test(id)\nif (!isValidModelId(modelId)) throw new Error(`Invalid modelId: ${modelId}`)","typeGuard":"const isValidModelId = (id: unknown): id is string =>\n  typeof id === 'string' && id.length > 0 && /^[A-Za-z0-9/_.\\-]+$/.test(id)","tryCatchPattern":"try {\n  await mlx.import(modelId, opts)\n} catch (e) {\n  if (String(e).includes('Invalid modelId')) {\n    throw new Error(`modelId \"${modelId}\" contains illegal characters; use [A-Za-z0-9/_.-] only`)\n  }\n  throw e\n}","preventionTips":["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"],"tags":["validation","input","model-import"],"backgroundTag":"invalid-identifier-format","analyzedSha":"7205d770c1e097c3daf35a911176410e93bc5564","analyzedAt":"2026-09-17T14:27:30.100Z","contentChangedAt":"2026-09-17T14:27:30.100Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}