From bdc3cbcabf7ce105e91512e51ce6031a879231b4 Mon Sep 17 00:00:00 2001 From: Sebastien Haentjens Date: Fri, 21 Nov 2025 17:04:15 +0100 Subject: [PATCH] Fix parsing of GRIB2 files without Section 2 (Local Use Section) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Section 2 (Local Use Section) is optional in GRIB2 files according to the WMO GRIB2 specification, and it is recommended not to use it for international data exchange. However, the library was always attempting to parse Section 2, causing incorrect section offsets when it was absent. This resulted in the parser reading subsequent sections with wrong offsets, leading to errors like "PRODUCT_DEFINITION_TEMPLATE_NOT_SUPPORTED" with bogus template numbers. Changes: - Modified parseAllSections() to check if Section 2 is present by reading the section number byte (offset +4 after the section length) - Only parse Section 2 if the section number is 2 - Properly adjust offsets for Section 3 and subsequent sections whether or not Section 2 is present This fix maintains backward compatibility with GRIB2 files that include Section 2 (like DWD files) while also supporting files that omit it (like Météo-France Arome files and other standard GRIB2 files). All existing tests pass with this change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- index.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 1ab5ba9..aad00df 100644 --- a/index.js +++ b/index.js @@ -300,8 +300,18 @@ function parseAllSections(gribBuffer, startIndex) { } const section1 = parseSection1(gribBuffer, section0.startIndex + section0.lengthOfRawData) - const section2 = parseSection2(gribBuffer, section1.startIndex + section1.lengthOfRawData) - const section3 = parseSection3(gribBuffer, section2.startIndex + section2.lengthOfRawData) + + // Check if Section 2 (Local Use Section) is present - it's optional in GRIB2 + let nextPos = section1.startIndex + section1.lengthOfRawData + const nextSectionNumber = gribBuffer[nextPos + 4] + + let section2 = null + if (nextSectionNumber === 2) { + section2 = parseSection2(gribBuffer, nextPos) + nextPos = section2.startIndex + section2.lengthOfRawData + } + + const section3 = parseSection3(gribBuffer, nextPos) const section4 = parseSection4(gribBuffer, section3.startIndex + section3.lengthOfRawData, section1.data.referenceTimestamp) const section5 = parseSection5(gribBuffer, section4.startIndex + section4.lengthOfRawData) const section6 = parseSection6(gribBuffer, section5.startIndex + section5.lengthOfRawData)