{"record":{"id":"81d31802a03f1006","repo":"janhq/jan","slug":"invalid-gguf-file-s-error-message-file-for","errorCode":null,"errorMessage":"Invalid GGUF file(s): ${error.message || 'File format validation failed'}","messagePattern":"Invalid GGUF file\\(s\\): (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"extensions/llamacpp-extension/src/index.ts","lineNumber":3273,"sourceCode":"      if (mmprojPath) {\n        const fullMmprojPath = await joinPath([janDataFolderPath, mmprojPath])\n        const mmprojMetadata = await readGgufMetadata(fullMmprojPath)\n        logger.info(\n          `Mmproj GGUF validation successful: version ${mmprojMetadata.version}, tensors: ${mmprojMetadata.tensor_count}`\n        )\n      }\n\n      // Validate MTP draft and read its head count (the main gguf usually\n      // lacks nextn_predict_layers when MTP ships as a separate file).\n      if (mtpModelPath) {\n        const fullMtpPath = await joinPath([janDataFolderPath, mtpModelPath])\n        const mtpMetadata = await readGgufMetadata(fullMtpPath)\n        const draftLayers = detectMtpLayersFromGgufMeta(mtpMetadata.metadata)\n        mtpLayers = draftLayers > 0 ? draftLayers : Math.max(mtpLayers, 1)\n      }\n    } catch (error) {\n      logger.error('GGUF validation failed:', error)\n      throw new Error(\n        `Invalid GGUF file(s): ${\n          error.message || 'File format validation failed'\n        }`\n      )\n    }\n\n    // Calculate file sizes\n    let size_bytes = (await fs.fileStat(fullModelPath)).size\n    if (mmprojPath) {\n      size_bytes += (\n        await fs.fileStat(await joinPath([janDataFolderPath, mmprojPath]))\n      ).size\n    }\n    if (mtpModelPath) {\n      size_bytes += (\n        await fs.fileStat(await joinPath([janDataFolderPath, mtpModelPath]))\n      ).size\n    }","sourceCodeStart":3255,"sourceCodeEnd":3291,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/extensions/llamacpp-extension/src/index.ts#L3255-L3291","documentation":"Thrown by the catch block wrapping the GGUF validation section of runImport(). It calls readGgufMetadata() on the main model, the mmproj, and the optional MTP draft file; any failure (corrupt header, non-GGUF file, I/O error, missing nextn layer metadata) is caught here and re-thrown as a single Invalid GGUF file(s) error whose message embeds the underlying cause. This is the only place format-level integrity of the imported weights is enforced.","triggerScenarios":"The downloaded file is not actually a .gguf (HTML error page from a CDN, a .bin LLaMA pickle, a truncated download). The file is a valid GGUF but the header/metadata read failed (incomplete write, disk corruption). mmproj or mtp path points at the main model file by mistake. The mtp draft file lacks the expected metadata shape. readGgufMetadata throws on an unrecognized GGUF version.","commonSituations":"Download was truncated by a network drop or pause/resume but the size check was skipped. User pointed import at a stale-format GGUF from an older llama.cpp version. HuggingFace URL returned an HTML 'file not found' page that got saved as the .gguf. Cross-arch binary confusion (pointing at a compiled binary instead of weights).","solutions":["Re-download the model file - the most common cause is a truncated/corrupt download.","Confirm the file is genuinely a GGUF (check magic bytes 'GGUF' / 0x46554747 at the start) before importing.","Verify mmprojPath and mtpPath point at the correct companion files, not back at the main model.","If the GGUF is from an old llama.cpp version, reconvert/re-export with a current gguf-py or pick a newer release.","Check disk health and free space; a corrupt-on-write file fails metadata read."],"exampleFix":"// before\nawait provider.import('x', { modelPath: '/d/qwen.gguf' }) // throws - HTML error page saved as gguf\n// after - validate magic before importing\nasync function isGguf(p) {\n  const f = await fs.open(p, 'r'); const buf = Buffer.alloc(4); await f.read(buf, 0, 4, 0); await f.close()\n  return buf.toString('ascii') === 'GGUF'\n}\nif (!(await isGguf('/d/qwen.gguf'))) throw new Error('not a real GGUF - re-download')\nawait provider.import('x', { modelPath: '/d/qwen.gguf' })","handlingStrategy":"validation","validationCode":"// Quick GGUF magic-byte check before importing a local file\nasync function looksLikeGguf(p: string): Promise<boolean> {\n  const f = await fs.open(p, 'r'); const buf = Buffer.alloc(4)\n  await f.read(buf, 0, 4, 0); await f.close()\n  return buf.toString('ascii') === 'GGUF'\n}\nfor (const p of [opts.modelPath, opts.mmprojPath, opts.mtpPath].filter(Boolean) as string[]) {\n  if (!p.startsWith('https://') && !(await looksLikeGguf(p))) throw new Error(`${p} is not a GGUF - re-download`)\n}","typeGuard":"async function isGgufFile(p: string): Promise<boolean> {\n  const f = await fs.open(p, 'r'); const buf = Buffer.alloc(4)\n  await f.read(buf, 0, 4, 0); await f.close()\n  return buf.readUInt32LE(0) === 0x46554747\n}","tryCatchPattern":"try { await provider.import(modelId, opts) }\ncatch (e) {\n  if (/Invalid GGUF/.test(String(e))) { await provider.abortImport(modelId); opts.modelPath = await redownload(); await provider.import(modelId, opts) }\n  else throw e\n}","preventionTips":["Always run size + sha256 verification on downloads so truncation is caught before import.","Check GGUF magic bytes on the picked/downloaded file before importing.","Keep mmproj/mtp paths distinct from the main model path to avoid pointing at the wrong file."],"tags":["model","import","gguf","validation","corrupt-file","download"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}