[GH-ISSUE #6848] [Bug] GGUF storage validation silently assumes the modern Q8_1 block layout for legacy files #4186

Closed
opened 2026-10-31 00:47:32 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 23, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6848

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

The production model service reports a 360-byte, storage-consistent tensor for a synthetic GGUF v3 declaration containing 320 Q8_1 elements encoded as ten historical 40-byte blocks. Its derived tensor-byte total is also 360, and coverage.storage_sizes is complete. A retained tensor page repeats the 360-byte range. There is no limitation identifying a historical-layout assumption.

The expected 400-byte historical length is source-derived: the released llama.cpp b1500 layout defines a 32-element Q8_1 block containing two 32-bit floats and 32 signed bytes. That implementation was source-inspected, not built or executed. The REA result below was executed on harmless synthetic input; no historical model or inference runtime was run.

Reproduction

From the source checkout with its locked dependencies, save this as /tmp/rea-legacy-q8.mts, then run:

REA_ROOT="$PWD" node --import ./node_modules/tsx/dist/loader.mjs /tmp/rea-legacy-q8.mts
import { pathToFileURL } from 'node:url';
import { writeFile } from 'node:fs/promises';
import { performance } from 'node:perf_hooks';
const root = process.env.REA_ROOT!;
const { createModelArtifactService } = await import(pathToFileURL(
  `${root}/src/composition/model.ts`).href);
const { inspectAnalysisView } = await import(pathToFileURL(
  `${root}/src/application/analysisView/AnalysisViewService.ts`).href);
const u32 = (n: number) => { const b=Buffer.alloc(4); b.writeUInt32LE(n); return b; };
const u64 = (n: number) => { const b=Buffer.alloc(8); b.writeBigUInt64LE(BigInt(n)); return b; };
const text = (s: string) => Buffer.concat([u64(Buffer.byteLength(s)),Buffer.from(s)]);
const header=Buffer.concat([
  Buffer.from('GGUF'),u32(3),u64(1),u64(2),
  text('general.architecture'),u32(8),text('llama'),
  text('general.quantization_version'),u32(4),u32(2),
  text('weight'),u32(1),u64(320),u32(9),u64(0),
]);
const start=Math.ceil(header.length/32)*32;
const file=Buffer.alloc(start+416); // 400 data bytes, then 16 alignment bytes.
header.copy(file);
file.fill(1,start,start+400);
const path='/tmp/rea-legacy-q8.gguf';
await writeFile(path,file);
const service=createModelArtifactService();
const started=performance.now();
try {
  const r=await service.inspect({path,detail:'complete'});
  if(!r.ok) throw r.error;
  const report=r.value.normalized_result as any;
  const page=await inspectAnalysisView({
    source:{kind:'retained-evidence',evidence_id:r.value.evidence_id},
    view:{kind:'model-artifact',collection:'tensors',names:['weight'],
      fields:['name','byte_length','storage_validation']},
  },(id: string)=>id===r.value.evidence_id?r.value:undefined);
  if(!page.ok) throw page.error;
  console.log(JSON.stringify({tensor:report.tensors[0],totals:report.totals,
    coverage:report.coverage,page_items:(page.value.normalized_result as any).items,
    elapsed_ms:Number((performance.now()-started).toFixed(3))},null,2));
} finally { await service.close(); }

This exact script ran once. A preceding three-case matrix used the same production service and retained-view boundary with F32, modern 36-byte Q8_1, and historical 40-byte Q8_1 layouts. All returned success; the controls reported their expected lengths, while the historical case reported the modern length.

Expected behavior

Preserve uncertainty about the storage layout when the available declarations cannot distinguish historical and modern Q8_1, or interpret a known historical layout with its corresponding length. A version-3/type-9 declaration alone does not establish that the modern block size applies to an old file.

REA advertises GGUF v2/v3 inspection. Released llama.cpp b1500, revision 57ad015dc3011b046ed5a23186c86ea55f987c54, defines 40-byte Q8_1 blocks, GGUF version 3, and quantization version 2. Its GGUF writer records tensor type and ggml_nbytes. Thus this historical storage distinction is not identified by the GGUF major version used in the reproduction.

Modern 36-byte Q8_1 blocks remain valid. The concern is the unconditional interpretation and complete storage validation for the historical case; this report does not justify changing every Q8_1 block size to 40.

Impact and scope

For the reduced historical-layout input, the reported tensor range omits 40 of 400 payload bytes, and the derived storage total is 10% too small. An analyst using the returned range for extraction would omit those bytes; extraction itself was not tested. Complete Evidence and retained views carry the same result.

Observed scope is synthetic GGUF v3 with type 9 and 320 elements. Historical artifact prevalence, other changed quantization layouts, CLI/MCP delivery, and behavior in an old reference reader remain unverified. Files are only read and remain unchanged.

REA version

Package version 6.7.0; source revision 9066444f6b8e9ffe1607a9b02cde3895a37db431. The published npm artifact was not executed separately.

Runtime and platform

Node.js v24.22.1; Linux x64, kernel 7.2.8-9-omarchy; locked source tsx loader. The inline source-service and view probe took 39.123 ms, excluding loader startup. The preceding matrix's historical case took 2.776 ms. These are individual observations, not benchmark estimates.

Target and artifact context

Self-authored 576-byte GGUF v3 file: 151-byte directory/header, data offset 160, 400 historical-layout payload bytes, and 16 trailing alignment bytes. The tensor declaration is weight, type 9 (Q8_1), shape [320], relative data offset 0. Metadata declares architecture llama and quantization version 2. The payload is synthetic; inference validity is outside this report.

Interface

Other

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Reduced executed output:

{
  "tensor": {
    "type": "Q8_1",
    "shape": ["320"],
    "file_offset": 160,
    "byte_length": 360,
    "storage_validation": "consistent"
  },
  "totals": { "tensor_bytes": 360 },
  "coverage": { "storage_sizes": "complete", "tensor_ranges": "complete" },
  "page_items": [
    { "index": 0, "name": "weight", "byte_length": 360, "storage_validation": "consistent" }
  ]
}

The executed F32 control returned 1,280 bytes for 320 elements. The modern Q8_1 control returned its expected 360 bytes. The historical source layout instead gives 320 / 32 * 40 = 400 bytes.

Evidence provenance: executed source-service and retained-view observations; source-derived historical layout and producer behavior. No independent historical-reader execution or real historical file acceptance is claimed.

Typed outcome or recovery expected

An explicit layout limitation with unknown storage size/validation when the layout cannot be established, while retaining the original type ID, shape, offsets, and source identity. Known legacy provenance can support the historical length without treating alignment padding as proof of a layout.

Analysis or suspected cause

Source-derived: ModelTensorTypes maps type 9 to 36 bytes, and GgufHeader derives length from that table. Once the derived range fits, it marks storage consistent. ModelArtifactProvider then reports complete storage coverage. None of these decisions records the historical-layout ambiguity.

Additional context

The supplied 1,065-open-report inventory contained no Q8_1 match. Live open/closed searches for Q8_1, GGUF block size, GGUF legacy, and GGUF storage found no exact report. Related feature #3666 concerns quantization reconstruction.

NOT_ENOUGH_INFO: first affected REA release, real-world historical Q8_1 prevalence, last known-good REA behavior, independent legacy-reader acceptance of this fixture, and a verified general workaround. The old source establishes a different published layout; the breadth of intended historical-layout support is not explicit. Prepared with AI assistance. All verification finished before this draft was created.

Triage assessment

  • Impact level: P2
  • Assessment status: provisional
  • Impact basis: The production source service and retained view report a shortened range with complete storage coverage for a reduced historical-layout declaration. The 400-byte legacy length is grounded in released producer/reader source, but real historical artifact prevalence and independent reader acceptance were not tested.
  • Workaround status: unverified
  • Workaround basis: An analyst with independently known legacy provenance could calculate the historical length from the released layout; a complete alternative inspection workflow and a way to distinguish unknown-provenance files were not verified.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6848 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior The production model service reports a 360-byte, storage-consistent tensor for a synthetic GGUF v3 declaration containing 320 Q8_1 elements encoded as ten historical 40-byte blocks. Its derived tensor-byte total is also 360, and `coverage.storage_sizes` is `complete`. A retained tensor page repeats the 360-byte range. There is no limitation identifying a historical-layout assumption. The expected 400-byte historical length is source-derived: the released llama.cpp b1500 layout defines a 32-element Q8_1 block containing two 32-bit floats and 32 signed bytes. That implementation was source-inspected, not built or executed. The REA result below was executed on harmless synthetic input; no historical model or inference runtime was run. ### Reproduction From the source checkout with its locked dependencies, save this as `/tmp/rea-legacy-q8.mts`, then run: ```sh REA_ROOT="$PWD" node --import ./node_modules/tsx/dist/loader.mjs /tmp/rea-legacy-q8.mts ``` ```ts import { pathToFileURL } from 'node:url'; import { writeFile } from 'node:fs/promises'; import { performance } from 'node:perf_hooks'; const root = process.env.REA_ROOT!; const { createModelArtifactService } = await import(pathToFileURL( `${root}/src/composition/model.ts`).href); const { inspectAnalysisView } = await import(pathToFileURL( `${root}/src/application/analysisView/AnalysisViewService.ts`).href); const u32 = (n: number) => { const b=Buffer.alloc(4); b.writeUInt32LE(n); return b; }; const u64 = (n: number) => { const b=Buffer.alloc(8); b.writeBigUInt64LE(BigInt(n)); return b; }; const text = (s: string) => Buffer.concat([u64(Buffer.byteLength(s)),Buffer.from(s)]); const header=Buffer.concat([ Buffer.from('GGUF'),u32(3),u64(1),u64(2), text('general.architecture'),u32(8),text('llama'), text('general.quantization_version'),u32(4),u32(2), text('weight'),u32(1),u64(320),u32(9),u64(0), ]); const start=Math.ceil(header.length/32)*32; const file=Buffer.alloc(start+416); // 400 data bytes, then 16 alignment bytes. header.copy(file); file.fill(1,start,start+400); const path='/tmp/rea-legacy-q8.gguf'; await writeFile(path,file); const service=createModelArtifactService(); const started=performance.now(); try { const r=await service.inspect({path,detail:'complete'}); if(!r.ok) throw r.error; const report=r.value.normalized_result as any; const page=await inspectAnalysisView({ source:{kind:'retained-evidence',evidence_id:r.value.evidence_id}, view:{kind:'model-artifact',collection:'tensors',names:['weight'], fields:['name','byte_length','storage_validation']}, },(id: string)=>id===r.value.evidence_id?r.value:undefined); if(!page.ok) throw page.error; console.log(JSON.stringify({tensor:report.tensors[0],totals:report.totals, coverage:report.coverage,page_items:(page.value.normalized_result as any).items, elapsed_ms:Number((performance.now()-started).toFixed(3))},null,2)); } finally { await service.close(); } ``` This exact script ran once. A preceding three-case matrix used the same production service and retained-view boundary with F32, modern 36-byte Q8_1, and historical 40-byte Q8_1 layouts. All returned success; the controls reported their expected lengths, while the historical case reported the modern length. ### Expected behavior Preserve uncertainty about the storage layout when the available declarations cannot distinguish historical and modern Q8_1, or interpret a known historical layout with its corresponding length. A version-3/type-9 declaration alone does not establish that the modern block size applies to an old file. REA [advertises GGUF v2/v3 inspection](https://github.com/morluto/rea/blob/9066444f6b8e9ffe1607a9b02cde3895a37db431/docs/model-artifacts.md#L3-L11). Released llama.cpp b1500, revision `57ad015dc3011b046ed5a23186c86ea55f987c54`, defines [40-byte Q8_1 blocks](https://github.com/ggml-org/llama.cpp/blob/57ad015dc3011b046ed5a23186c86ea55f987c54/ggml-quants.h#L49-L55), [GGUF version 3](https://github.com/ggml-org/llama.cpp/blob/57ad015dc3011b046ed5a23186c86ea55f987c54/ggml.h#L234-L238), and [quantization version 2](https://github.com/ggml-org/llama.cpp/blob/57ad015dc3011b046ed5a23186c86ea55f987c54/ggml.h#L213-L214). Its [GGUF writer records tensor type and ggml_nbytes](https://github.com/ggml-org/llama.cpp/blob/57ad015dc3011b046ed5a23186c86ea55f987c54/ggml.c#L19337-L19358). Thus this historical storage distinction is not identified by the GGUF major version used in the reproduction. Modern 36-byte Q8_1 blocks remain valid. The concern is the unconditional interpretation and complete storage validation for the historical case; this report does not justify changing every Q8_1 block size to 40. ### Impact and scope For the reduced historical-layout input, the reported tensor range omits 40 of 400 payload bytes, and the derived storage total is 10% too small. An analyst using the returned range for extraction would omit those bytes; extraction itself was not tested. Complete Evidence and retained views carry the same result. Observed scope is synthetic GGUF v3 with type 9 and 320 elements. Historical artifact prevalence, other changed quantization layouts, CLI/MCP delivery, and behavior in an old reference reader remain unverified. Files are only read and remain unchanged. ### REA version Package version 6.7.0; source revision `9066444f6b8e9ffe1607a9b02cde3895a37db431`. The published npm artifact was not executed separately. ### Runtime and platform Node.js v24.22.1; Linux x64, kernel 7.2.8-9-omarchy; locked source tsx loader. The inline source-service and view probe took 39.123 ms, excluding loader startup. The preceding matrix's historical case took 2.776 ms. These are individual observations, not benchmark estimates. ### Target and artifact context Self-authored 576-byte GGUF v3 file: 151-byte directory/header, data offset 160, 400 historical-layout payload bytes, and 16 trailing alignment bytes. The tensor declaration is `weight`, type 9 (`Q8_1`), shape `[320]`, relative data offset 0. Metadata declares architecture `llama` and quantization version 2. The payload is synthetic; inference validity is outside this report. ### Interface Other ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence Reduced executed output: ```json { "tensor": { "type": "Q8_1", "shape": ["320"], "file_offset": 160, "byte_length": 360, "storage_validation": "consistent" }, "totals": { "tensor_bytes": 360 }, "coverage": { "storage_sizes": "complete", "tensor_ranges": "complete" }, "page_items": [ { "index": 0, "name": "weight", "byte_length": 360, "storage_validation": "consistent" } ] } ``` The executed F32 control returned 1,280 bytes for 320 elements. The modern Q8_1 control returned its expected 360 bytes. The historical source layout instead gives `320 / 32 * 40 = 400` bytes. Evidence provenance: executed source-service and retained-view observations; source-derived historical layout and producer behavior. No independent historical-reader execution or real historical file acceptance is claimed. ### Typed outcome or recovery expected An explicit layout limitation with unknown storage size/validation when the layout cannot be established, while retaining the original type ID, shape, offsets, and source identity. Known legacy provenance can support the historical length without treating alignment padding as proof of a layout. ### Analysis or suspected cause Source-derived: [ModelTensorTypes maps type 9 to 36 bytes](https://github.com/morluto/rea/blob/9066444f6b8e9ffe1607a9b02cde3895a37db431/src/model/ModelTensorTypes.ts#L13), and [GgufHeader derives length from that table](https://github.com/morluto/rea/blob/9066444f6b8e9ffe1607a9b02cde3895a37db431/src/model/GgufHeader.ts#L355-L367). Once the derived range fits, [it marks storage consistent](https://github.com/morluto/rea/blob/9066444f6b8e9ffe1607a9b02cde3895a37db431/src/model/GgufHeader.ts#L396-L410). [ModelArtifactProvider then reports complete storage coverage](https://github.com/morluto/rea/blob/9066444f6b8e9ffe1607a9b02cde3895a37db431/src/model/ModelArtifactProvider.ts#L438-L445). None of these decisions records the historical-layout ambiguity. ### Additional context The supplied 1,065-open-report inventory contained no Q8_1 match. Live open/closed searches for `Q8_1`, `GGUF block size`, `GGUF legacy`, and `GGUF storage` found no exact report. Related feature #3666 concerns quantization reconstruction. NOT_ENOUGH_INFO: first affected REA release, real-world historical Q8_1 prevalence, last known-good REA behavior, independent legacy-reader acceptance of this fixture, and a verified general workaround. The old source establishes a different published layout; the breadth of intended historical-layout support is not explicit. Prepared with AI assistance. All verification finished before this draft was created. ## Triage assessment - Impact level: P2 - Assessment status: provisional - Impact basis: The production source service and retained view report a shortened range with complete storage coverage for a reduced historical-layout declaration. The 400-byte legacy length is grounded in released producer/reader source, but real historical artifact prevalence and independent reader acceptance were not tested. - Workaround status: unverified - Workaround basis: An analyst with independently known legacy provenance could calculate the historical length from the released layout; a complete alternative inspection workflow and a way to distinguish unknown-provenance files were not verified.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#4186
No description provided.