{"record":{"id":"a64f1002451c19c9","repo":"gchq/CyberChef","slug":"exhausted-buffer","errorCode":null,"errorMessage":"Exhausted Buffer","messagePattern":"Exhausted Buffer","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/core/lib/Protobuf.mjs","lineNumber":375,"sourceCode":"\n    // Private Class Functions\n\n    /**\n     * Main private parsing function\n     *\n     * @private\n     * @returns {Object}\n     */\n    _parse() {\n        let object = {};\n        // Continue reading whilst we still have data\n        while (this.offset < this.LENGTH) {\n            const field = this._parseField();\n            object = this._addField(field, object);\n        }\n        // Throw an error if we have gone beyond the end of the data\n        if (this.offset > this.LENGTH) {\n            throw new Error(\"Exhausted Buffer\");\n        }\n        return object;\n    }\n\n    /**\n     * Add a field read from the protobuf data into the Object. As\n     * protobuf fields can appear multiple times, if the field already\n     * exists we need to add the new field into an array of fields\n     * for that key.\n     *\n     * @private\n     * @param {Object} field\n     * @param {Object} object\n     * @returns {Object}\n     */\n    _addField(field, object) {\n        // Get the field key/values\n        const key = field.key;","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Protobuf.mjs#L357-L393","documentation":"Thrown by Protobuf._parse when, after consuming all fields, the internal offset has overshot this.LENGTH — meaning a varint, length-delimited block, or fixed-size field claimed more bytes than the buffer actually held. The raw (schemaless) decoder refuses to silently truncate.","triggerScenarios":"Decoding bytes where a length-delimited field declares N bytes but fewer remain; a varint runs past the end; a fixed32/fixed64 read crosses the buffer boundary; corrupted/truncated protobuf payload.","commonSituations":"Hand-edited hex that miscounts a length prefix; partial network frame; concatenation bug leaving a stray trailing byte that looks like a field header; feeding non-protobuf binary.","solutions":["Verify the input is complete and well-formed protobuf (re-encode with a known-good library and compare).","Check length-delimited prefixes against the actual remaining bytes before decode.","Strip trailing padding/garbage so offset lands exactly on this.LENGTH."],"exampleFix":"// before: a length prefix says 10 bytes but only 4 remain\n// after: correct the length prefix to the real payload size","handlingStrategy":"validation","validationCode":"function wellFormedProtobuf(bytes) {\n  try { new Protobuf(bytes)._parse(); return true; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  return new Protobuf(input)._parse();\n} catch (e) {\n  if (/Exhausted Buffer/.test(e.message)) {\n    // input is truncated or a length prefix lies — re-acquire the full payload\n  }\n  throw e;\n}","preventionTips":["Validate length-delimited prefixes against remaining bytes before decode.","Ensure the buffer is complete (not a partial frame) before parsing.","Strip accidental trailing padding bytes."],"tags":["protobuf","decode","buffer","truncation","validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}