nodejs/node · error

unable to create an empty bundle for the pool keys

Error message

unable to create an empty bundle for the pool keys: %s

What it means

While initializing a fresh pool bundle (the keys-only bundle written by --writePoolBundle), genrb constructs `new SRBRoot(nullptr, true, status)`. If that constructor reports a failure via the UErrorCode (typically U_MEMORY_ALLOCATION_ERROR), the message prints the human-readable code via u_errorName and returns it. The pool bundle is the shared key table that other .res files reference to reduce size.

Solutions

  1. Free memory or raise the container's memory limit before re-running.
  2. Reduce parallelism in the data build so each genrb process has enough headroom.
  3. Inspect the status string printed (e.g. U_MEMORY_ALLOCATION_ERROR) to confirm it is a memory problem rather than a logic error.
Defensive patterns

Strategy: try-catch

Validate before calling

# Best-effort preflight: ensure enough free memory for the build
min_mb=512
free_mb=$(awk '/MemAvailable/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo 0)
if [ "$free_mb" -lt "$min_mb" ]; then
  echo "WARNING: only ${free_mb}MB free; pool bundle init may fail" >&2
fi

Try / catch

genrb --writePoolBundle "$OUT_DIR" "$@" 2>err.log
if grep -q 'unable to create an empty bundle' err.log; then
  echo "Pool bundle init failed; freeing memory or reducing parallelism" >&2; exit 1
fi

Prevention

When it happens

Trigger: Running `genrb --writePoolBundle out/ *.txt` on a system under severe memory pressure, or with a corrupted/oversized input that causes the SRBRoot constructor to fail its internal allocations.

Common situations: Building ICU data inside a memory-limited container or CI runner; running many parallel genrb processes that exhaust RAM.

Related errors


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

Appendix: source

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

        CollationRoot::forceLoadFromFile(options[UCADATA].value, status);
#else
        fprintf(stderr, "--ucadata was used with UCONFIG_NO_COLLATION\n");
        return status;
#endif
    }

    initParser();

    /*added by Jing*/
    if(options[LANGUAGE].doesOccur) {
        language = options[LANGUAGE].value;
    }

    LocalPointer<SRBRoot> newPoolBundle;
    if(options[WRITE_POOL_BUNDLE].doesOccur) {
        newPoolBundle.adoptInsteadAndCheckErrorCode(new SRBRoot(nullptr, true, status), status);
        if(U_FAILURE(status)) {
            fprintf(stderr, "unable to create an empty bundle for the pool keys: %s\n", u_errorName(status));
            return status;
        } else {
            const char *poolResName = "pool.res";
            char *nameWithoutSuffix = static_cast<char *>(uprv_malloc(uprv_strlen(poolResName) + 1));
            if (nameWithoutSuffix == nullptr) {
                fprintf(stderr, "out of memory error\n");
                return U_MEMORY_ALLOCATION_ERROR;
            }
            uprv_strcpy(nameWithoutSuffix, poolResName);
            *uprv_strrchr(nameWithoutSuffix, '.') = 0;
            newPoolBundle->fLocale = nameWithoutSuffix;
        }
    }

    if(options[USE_POOL_BUNDLE].doesOccur) {
        const char *poolResName = "pool.res";
        FileStream *poolFile;
        int32_t poolFileSize;

View on GitHub (pinned to 1b2de5e052)