ruvnet/ruflo · error · Error

String length ${len} exceeds remaining buffer

Error message

String length ${len} exceeds remaining buffer

What it means

Thrown by BufferReader.readString while parsing a GGUF file. GGUF strings are encoded as a u64 length prefix followed by UTF-8 bytes; readString reads the length with readU64AsNumber and rejects it if it exceeds reader.remaining. This protects against truncated or malformed files that would otherwise read past the buffer end (the parse reads at most the first 256 KB of the file, so legitimate large strings can still trip this).

Source

Thrown at v3/@claude-flow/cli/src/appliance/gguf-engine.ts:99

  readU8(): number  { const v = this.buf.readUInt8(this.offset); this.offset += 1; return v; }
  readI8(): number  { const v = this.buf.readInt8(this.offset); this.offset += 1; return v; }
  readU16(): number { const v = this.buf.readUInt16LE(this.offset); this.offset += 2; return v; }
  readI16(): number { const v = this.buf.readInt16LE(this.offset); this.offset += 2; return v; }
  readU32(): number { const v = this.buf.readUInt32LE(this.offset); this.offset += 4; return v; }
  readI32(): number { const v = this.buf.readInt32LE(this.offset); this.offset += 4; return v; }
  readF32(): number { const v = this.buf.readFloatLE(this.offset); this.offset += 4; return v; }
  readF64(): number { const v = this.buf.readDoubleLE(this.offset); this.offset += 8; return v; }
  readU64(): bigint { const v = this.buf.readBigUInt64LE(this.offset); this.offset += 8; return v; }
  readI64(): bigint { const v = this.buf.readBigInt64LE(this.offset); this.offset += 8; return v; }
  /** Safe for values up to 2^53. Real GGUF files never exceed this for tensor/kv counts. */
  readU64AsNumber(): number { return Number(this.readU64()); }
  readBool(): boolean { return this.readU8() !== 0; }

  /** GGUF string: [length u64 LE][utf-8 bytes]. */
  readString(): string {
    const len = this.readU64AsNumber();
    if (len === 0) return '';
    if (len > this.remaining) throw new Error(`String length ${len} exceeds remaining buffer`);
    const s = this.buf.toString('utf-8', this.offset, this.offset + len);
    this.offset += len;
    return s;
  }
}

// ── GGUF Value Reading ──────────────────────────────────────

/** Read a typed scalar from the buffer (shared by value and array-element readers). */
function readScalar(reader: BufferReader, t: number): unknown {
  switch (t) {
    case GgufValueType.UINT8:   return reader.readU8();
    case GgufValueType.INT8:    return reader.readI8();
    case GgufValueType.UINT16:  return reader.readU16();
    case GgufValueType.INT16:   return reader.readI16();
    case GgufValueType.UINT32:  return reader.readU32();
    case GgufValueType.INT32:   return reader.readI32();
    case GgufValueType.FLOAT32: return reader.readF32();

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Verify the file is a complete, valid GGUF (check file size against the source, re-download if truncated).
  2. Confirm you are pointing at a real GGUF file and not a different format renamed .gguf.
  3. If the model legitimately has very large metadata strings, the 256 KB header window in parseGgufHeader is the limit — request/produce a GGUF with smaller string metadata or extend the read size.
  4. Validate the file with an external GGUF inspector (e.g. llama.cpp) to isolate corruption from parser limitations.

Example fix

// before
const meta = await parseGgufHeader('/models/possibly-corrupt.gguf');

// after
const stat = await fsStat(path);
if (stat.size < 1024) throw new Error('file too small to be a valid GGUF');
const meta = await parseGgufHeader(path);
Defensive patterns

Strategy: validation

Validate before calling

const stat = await fsStat(path);
if (stat.size < 1024) {
  throw new Error('file too small to be a valid GGUF');
}
const meta = await parseGgufHeader(path);

Type guard

function looksLikeCompleteGguf(stat: { size: number }): boolean {
  return stat.size >= 1024; // heuristic: a real GGUF is at least kilobytes
}

Try / catch

try {
  return await parseGgufHeader(path);
} catch (e) {
  if (e instanceof Error && /exceeds remaining buffer/.test(e.message)) {
    logger.error({ path }, 'GGUF truncated or corrupt');
  }
  throw e;
}

Prevention

When it happens

Trigger: Parsing a GGUF file whose metadata declares a string longer than the bytes left in the 256 KB header window, a file truncated mid-metadata, or a corrupt length prefix (e.g. garbage read as u64). Also possible for models with unusually large string metadata that exceeds the 256 KB read window.

Common situations: Downloading a model file incompletely (truncated transfer), pointing parseGgufHeader at a non-GGUF file, or a model whose tokenizer vocabulary is stored as one giant string exceeding the 256 KB cap. The catch in parseGgufBuffer swallows some of these during the KV loop, but the throw still propagates elsewhere.

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/b7242bbcdd139014. Report an issue: GitHub.