ruvnet/ruflo · error · Error
Invalid GGUF magic: 0x${magic.toString(16)} (expected 0x${GG
Error message
Invalid GGUF magic: 0x${magic.toString(16)} (expected 0x${GGUF_MAGIC.toString(16)}) What it means
Thrown by parseGgufBuffer when the first u32 of the file is not GGUF_MAGIC. The magic number is the format's identity check; a mismatch means the file is not GGUF (or is a different endianness / a different format that happens to be passed in). This is the earliest possible parse failure and runs before version/tensor/KV reads.
Source
Thrown at v3/@claude-flow/cli/src/appliance/gguf-engine.ts:170
export async function parseGgufHeader(path: string): Promise<GgufMetadata> {
const fileInfo = await fsStat(path);
const readSize = Math.min(fileInfo.size, 256 * 1024);
const fh = await open(path, 'r');
try {
const buf = Buffer.alloc(readSize);
await fh.read(buf, 0, readSize, 0);
return parseGgufBuffer(buf, fileInfo.size, path);
} finally {
await fh.close();
}
}
function parseGgufBuffer(buf: Buffer, fileSize: number, filePath: string): GgufMetadata {
const reader = new BufferReader(buf);
const magic = reader.readU32();
if (magic !== GGUF_MAGIC) {
throw new Error(`Invalid GGUF magic: 0x${magic.toString(16)} (expected 0x${GGUF_MAGIC.toString(16)})`);
}
const version = reader.readU32();
if (version < 2 || version > 3) {
throw new Error(`Unsupported GGUF version: ${version} (expected 2 or 3)`);
}
const tensorCount = reader.readU64AsNumber();
const kvCount = reader.readU64AsNumber();
const metadata: Record<string, unknown> = {};
for (let i = 0; i < kvCount; i++) {
if (reader.remaining < 12) break;
try {
const key = reader.readString();
metadata[key] = readGgufValue(reader);
} catch {
break; // reached end of read windowView on GitHub (pinned to 6b01dc5a68)
Solutions
- Confirm the path points to an actual GGUF file (check the file command / first bytes; GGUF magic is 'GGUF' = 0x46554747).
- Re-download from the source if the file looks like an HTML error page or is suspiciously small.
- Gate parseGgufHeader with a quick magic-byte check so you can give a clearer error or skip non-GGUF files in a directory scan.
- Verify the file was not truncated to zero bytes by a failed transfer.
Example fix
// before
const meta = await parseGgufHeader(candidatePath);
// after
async function isGguf(path: string): Promise<boolean> {
const fh = await open(path, 'r');
const head = Buffer.alloc(4);
await fh.read(head, 0, 4, 0);
await fh.close();
return head.readUInt32LE(0) === 0x46554747;
}
if (!(await isGguf(candidatePath))) throw new Error('not a GGUF file; refusing to parse'); Defensive patterns
Strategy: validation
Validate before calling
import { open } from 'node:fs/promises';
async function isGgufFile(path: string): Promise<boolean> {
const fh = await open(path, 'r');
const head = Buffer.alloc(4);
await fh.read(head, 0, 4, 0);
await fh.close();
return head.readUInt32LE(0) === 0x46554747; // 'GGUF'
}
if (!(await isGgufFile(path))) throw new Error('not a GGUF file'); Type guard
function isGgufMagic(buf: Buffer): boolean {
return buf.length >= 4 && buf.readUInt32LE(0) === 0x46554747;
} Try / catch
try {
return await parseGgufHeader(path);
} catch (e) {
if (e instanceof Error && /Invalid GGUF magic/.test(e.message)) {
throw new Error(`'${path}' is not a GGUF file`);
}
throw e;
} Prevention
- Filter directory scans by .gguf extension AND magic bytes.
- Re-download files that look like HTML error pages saved as .gguf.
- Do not feed tokenizer/config files to the GGUF parser.
- Check the file is non-empty before parsing.
When it happens
Trigger: Calling parseGgufHeader (or otherwise parsing) on a file that is not GGUF: a safetensors/GGML/bin file, a text file, or a renamed download. Also fires if the file is empty or only a few bytes long so the u32 read yields zeros.
Common situations: Wrong file selected in a model picker (e.g. a tokenizer or config JSON named .gguf), a download that produced an HTML error page saved with the .gguf extension, or endianness confusion. The message helpfully prints both the found and expected magic in hex.
Related errors
- String length ${len} exceeds remaining buffer
- Unknown GGUF array element type: ${elemType}
- Unknown GGUF value type: ${valueType}
- Unsupported GGUF version: ${version} (expected 2 or 3)
- KV cache file too small
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/8836fefc1b7f647a.
Report an issue: GitHub.