tobi/qmd · error · Error

Model file is not valid GGUF (expected magic "GGUF", got "${

Error message

Model file is not valid GGUF (expected magic "GGUF", got "${inspection.magic ?? "unknown"}", file is ${formatModelFileSize(inspection.sizeBytes ?? 0)}).\nModel: ${modelUri}\nPath:  ${filePath}\n\nThe file has been removed. Run the command again to re-download.

What it means

validateGgufFile found the downloaded file does not start with the required 'GGUF' magic bytes, so it is not a usable model file. Unlike the HTML case, this catches truncated/corrupted downloads; the file has already been deleted and re-running the command will download it again.

Source

Thrown at src/llm.ts:476

  try {
    unlinkSync(filePath);
  } catch { /* best effort */ }

  if (inspection.kind === "html") {
    throw new Error(
      `Downloaded model file is an HTML page, not a GGUF model (${formatModelFileSize(inspection.sizeBytes ?? 0)}).\n` +
      `Something is intercepting the download from huggingface.co (a proxy, firewall, or captive portal).\n\n` +
      `Model: ${modelUri}\n` +
      `Path:  ${filePath}\n\n` +
      `To fix this, either:\n` +
      `  1. Try a HuggingFace mirror:  HF_ENDPOINT=https://hf-mirror.com qmd embed\n` +
      `  2. Download the model manually and set the env var, e.g.:\n` +
      `       QMD_EMBED_MODEL=/path/to/model.gguf qmd embed\n\n` +
      `Note: 'qmd search' works without any model downloads.`
    );
  }

  throw new Error(
    `Model file is not valid GGUF (expected magic "GGUF", got "${inspection.magic ?? "unknown"}", file is ${formatModelFileSize(inspection.sizeBytes ?? 0)}).\n` +
    `Model: ${modelUri}\n` +
    `Path:  ${filePath}\n\n` +
    `The file has been removed. Run the command again to re-download.`
  );
}


/**
 * node-llama-cpp prints a multi-line download progress bar when the second
 * argument is a directory string (`cli` defaults to true). Agent transcripts
 * capture that as thousands of tokens. Always pass an options object so the
 * bar is off unless the caller opts in (#776).
 */
function resolveModelFileArgs(cacheDir: string, cli = false): { directory: string; cli: boolean } {
  return { directory: cacheDir, cli };
}

View on GitHub (pinned to dbfd0b4736)

Solutions

  1. Simply re-run the command — the bad file is removed and will re-download
  2. If it recurs, check disk space and network stability, or verify the mirror with HF_ENDPOINT
  3. Download the model manually from huggingface.co and set QMD_EMBED_MODEL=/path/to/model.gguf
  4. If using a manual path, confirm the file starts with the bytes 'GGUF' (e.g. head -c 4 file | xxd)
Defensive patterns

Strategy: retry

Validate before calling

function isGguf(filePath: string): boolean {
  const fd = openSync(filePath, 'r');
  const buf = Buffer.alloc(4);
  readSync(fd, buf, 0, 4, 0); closeSync(fd);
  return buf.toString('utf-8') === 'GGUF';
}

Try / catch

for (let attempt = 1; attempt <= 3; attempt++) {
  try { await pullModels(); break; }
  catch (e) {
    if (e instanceof Error && e.message.includes('not valid GGUF') && attempt < 3) continue;
    throw e;
  }
}

Prevention

When it happens

Trigger: A model download interrupted mid-stream (disk full, process killed, connection dropped) leaving a partial file; a mirror or cache serving corrupted content; a manual QMD_EMBED_MODEL path pointing at a non-GGUF file.

Common situations: Killed qmd embed mid-download; flaky networks truncating large files; HF mirror serving bad artifacts; pointing QMD_EMBED_MODEL at a .bin or partially-downloaded file.

Related errors


AI-assisted analysis of tobi/qmd@dbfd0b4736 (2026-08-28). Data as JSON: /api/errors/1efe0ab89fa247c6. Report an issue: GitHub.