nodejs/node · critical

U_MEMORY_ALLOCATION_ERROR

U_MEMORY_ALLOCATION_ERROR

Error message

error: %s - out of memory

What it means

Fatal out-of-memory error in utm_open() — the UToolMemory allocation function. When uprv_malloc fails to allocate the initial UToolMemory struct plus the static array (sizeof(UToolMemory) + initialCapacity * size bytes), the tool prints the error with the memory block's name and exits with U_MEMORY_ALLOCATION_ERROR. This is an unrecoverable condition — the process terminates immediately.

Source

Thrown at deps/icu-small/source/tools/toolutil/toolutil.cpp:353

struct UToolMemory {
    char name[64];
    int32_t capacity, maxCapacity, size, idx;
    void *array;
    alignas(std::max_align_t) char staticArray[1];
};

U_CAPI UToolMemory * U_EXPORT2
utm_open(const char *name, int32_t initialCapacity, int32_t maxCapacity, int32_t size) {
    UToolMemory *mem;

    if(maxCapacity<initialCapacity) {
        maxCapacity=initialCapacity;
    }

    mem=(UToolMemory *)uprv_malloc(sizeof(UToolMemory)+initialCapacity*size);
    if(mem==nullptr) {
        fprintf(stderr, "error: %s - out of memory\n", name);
        exit(U_MEMORY_ALLOCATION_ERROR);
    }
    mem->array=mem->staticArray;

    uprv_strcpy(mem->name, name);
    mem->capacity=initialCapacity;
    mem->maxCapacity=maxCapacity;
    mem->size=size;
    mem->idx=0;
    return mem;
}

U_CAPI void U_EXPORT2
utm_close(UToolMemory *mem) {
    if(mem!=nullptr) {
        if(mem->array!=mem->staticArray) {
            uprv_free(mem->array);
        }

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Reduce the initialCapacity parameter passed to utm_open() if it is unreasonably large.
  2. Free other memory allocations before calling utm_open() to reduce overall memory pressure.
  3. Build on a system with more available RAM or swap space.
  4. If on a 32-bit system, switch to a 64-bit build to remove address space limits.
  5. Check for memory leaks in the build tool using Valgrind or AddressSanitizer.

Example fix

// before
UToolMemory *mem = utm_open("bigdata", 10000000, 10000000, sizeof(int32_t));
// after — smaller initial capacity with growth
UToolMemory *mem = utm_open("bigdata", 1024, 10000000, sizeof(int32_t));
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check available memory before utm_open (heuristic)
#include <sys/resource.h>
#include <unistd.h>

bool canAllocate(size_t bytes) {
#ifdef _SC_AVPHYS_PAGES
    long pages = sysconf(_SC_AVPHYS_PAGES);
    long pageSize = sysconf(_SC_PAGE_SIZE);
    if (pages > 0 && pageSize > 0) {
        size_t avail = (size_t)pages * (size_t)pageSize;
        return (avail > bytes * 2); // 2x safety margin
    }
#endif
    return true; // Cannot determine; proceed optimistically
}

bool safeUtmOpen(size_t initialCapacity, int32_t size) {
    size_t needed = sizeof(UToolMemory) + initialCapacity * size;
    return canAllocate(needed);
}

Try / catch

// utm_open calls exit() on failure — there is no try-catch recovery.
// To guard, check memory availability before calling:
if (!canAllocate(sizeof(UToolMemory) + (size_t)initCap * elemSize)) {
    fprintf(stderr, "Insufficient memory for utm_open; aborting gracefully\n");
    return EXIT_FAILURE;
}
UToolMemory* mem = utm_open(name, initCap, maxCap, elemSize);

Prevention

When it happens

Trigger: utm_open() is called with a large initialCapacity * size product that exceeds available memory, or the system is under severe memory pressure. The uprv_malloc returns nullptr, triggering exit(U_MEMORY_ALLOCATION_ERROR). Used throughout ICU data generation tools for dynamic array management.

Common situations: Building ICU data on systems with insufficient RAM; requesting an excessively large initial capacity; memory leaks in long-running build processes depleting available memory; 32-bit process address space limits.

Related errors


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