nodejs/node · critical

U_INTERNAL_PROGRAM_ERROR

U_INTERNAL_PROGRAM_ERROR

Error message

genrb error: wrote %u bytes but counted %u

What it means

After writing all bundle contents to a UDataMemory block, genrb calls udata_finish() to get the actual bytes written and compares it to the pre-computed 'top' offset. If these do not match, it indicates an internal bug in genrb's size accounting: the code counted a different number of bytes than it actually wrote. Sets U_INTERNAL_PROGRAM_ERROR — this is never a user input error.

Source

Thrown at deps/icu-small/source/tools/genrb/reslist.cpp:1088

    /* write the indexes[] */
    udata_writeBlock(mem, indexes, fIndexLength*4);

    /* write the table key strings */
    udata_writeBlock(mem, fKeys+fKeysBottom,
                          fKeysTop-fKeysBottom);

    /* write the v2 UTF-16 strings, URES_TABLE16 and URES_ARRAY16 */
    udata_writeBlock(mem, f16BitUnits.getBuffer(), f16BitUnits.length()*2);

    /* write all of the bundle contents: the root item and its children */
    byteOffset = fKeysTop + f16BitUnits.length() * 2;
    fRoot->write(mem, &byteOffset);
    assert(byteOffset == top);

    size = udata_finish(mem, &errorCode);
    if(top != size) {
        fprintf(stderr, "genrb error: wrote %u bytes but counted %u\n",
                static_cast<int>(size), static_cast<int>(top));
        errorCode = U_INTERNAL_PROGRAM_ERROR;
    }
}

/* Opening Functions */

TableResource* table_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status) {
    LocalPointer<TableResource> res(new TableResource(bundle, tag, comment, *status), *status);
    return U_SUCCESS(*status) ? res.orphan() : nullptr;
}

ArrayResource* array_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status) {
    LocalPointer<ArrayResource> res(new ArrayResource(bundle, tag, comment, *status), *status);
    return U_SUCCESS(*status) ? res.orphan() : nullptr;
}

struct SResource *string_open(struct SRBRoot *bundle, const char *tag, const char16_t *value, int32_t len, const struct UString* comment, UErrorCode *status) {

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Report this as an ICU bug — U_INTERNAL_PROGRAM_ERROR in this path is always a genrb defect, not user error
  2. Try a different ICU version (upgrade or downgrade) to see if the bug is fixed
  3. Simplify the resource bundle structure to avoid the triggering edge case (reduce nesting depth, split large arrays)
  4. Build genrb with debug assertions enabled (NDEBUG undefined) so the assert catches the discrepancy earlier
  5. If possible, restructure the resource bundle to avoid mixed 16-bit/32-bit resource types that may trigger the counting bug
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: This error is produced by a bug in genrb's own byte-counting logic. The fRoot->write() function, key writing, or 16-bit unit writing computed offsets that don't match what udata_write actually produced. The assert(byteOffset == top) on the preceding line either passed (in release builds) or would have caught a different class of the same bug.

Common situations: Using a version of ICU with a known genrb size-accounting bug; building resource bundles with unusual structures (deeply nested tables, very large arrays, mixed 16-bit and 32-bit resources) that expose an edge case in the size calculator; building with compiler optimizations that expose undefined behavior in genrb's pointer arithmetic.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/e0f75ec90692b4ef. Report an issue: GitHub.