dotnet/runtime · critical
max-heap-size must be at least %dMb.\n
Error message
max-heap-size must be at least %dMb.\n
What it means
Emitted during Mono Boehm GC initialization in mono_gc_base_init (boehm-gc.c:171). The MONO_GC_PARAMS environment variable is comma-split and a `max-heap-size=` token is parsed by mono_gc_parse_environment_string_extract_number (which accepts an optional k/m/g suffix, converted to bytes via shifts). If the parsed value is below MIN_BOEHM_MAX_HEAP_SIZE (16 << 20 = 16 MiB) the runtime prints 'max-heap-size must be at least 16Mb.' and immediately calls exit(1) — the process dies at GC init, before managed code runs.
Source
Thrown at src/mono/mono/metadata/boehm-gc.c:171
GC_set_warn_proc (mono_gc_warning);
GC_set_finalize_on_demand (1);
GC_set_finalizer_notifier(mono_gc_finalize_notify);
GC_init_gcj_malloc (5, NULL);
GC_allow_register_threads ();
if ((env = g_getenv ("MONO_GC_PARAMS"))) {
char **ptr, **opts = g_strsplit (env, ",", -1);
for (ptr = opts; *ptr; ++ptr) {
char *opt = *ptr;
if (g_str_has_prefix (opt, "max-heap-size=")) {
size_t max_heap;
opt = strchr (opt, '=') + 1;
if (*opt && mono_gc_parse_environment_string_extract_number (opt, &max_heap)) {
if (max_heap < MIN_BOEHM_MAX_HEAP_SIZE) {
fprintf (stderr, "max-heap-size must be at least %dMb.\n", MIN_BOEHM_MAX_HEAP_SIZE_IN_MB);
exit (1);
}
GC_set_max_heap_size (max_heap);
} else {
fprintf (stderr, "max-heap-size must be an integer.\n");
exit (1);
}
continue;
} else if (g_str_has_prefix (opt, "toggleref-test")) {
register_test_toggleref_callback ();
continue;
} else {
/* Could be a parameter for sgen */
/*
fprintf (stderr, "MONO_GC_PARAMS must be a comma-delimited list of one or more of the following:\n");
fprintf (stderr, " max-heap-size=N (where N is an integer, possibly with a k, m or a g suffix)\n");
exit (1);
*/View on GitHub (pinned to 290d5ab72c)
Solutions
- Raise the value to at least 16m, e.g. MONO_GC_PARAMS=max-heap-size=64m.
- Remember the floor is 16 MiB: a suffixless number is bytes, 'k'=KiB, 'm'=MiB, 'g'=GiB; values like 15m and anything smaller are rejected.
- If you genuinely need a tiny heap, Boehm is the wrong collector — switch the runtime to sgen (which accepts smaller nurseries) or revisit the constraint.
- Validate MONO_GC_PARAMS in your launch wrapper before starting the runtime so a bad value fails fast with a clear message instead of exit(1).
- On Mono, confirm the active GC with `mono --version` / the runtime build; boehm-gc.c is only compiled when HAVE_BOEHM_GC is defined.
Example fix
# before $ MONO_GC_PARAMS=max-heap-size=8m mono app.exe max-heap-size must be at least 16Mb. # (process exits) # after $ MONO_GC_PARAMS=max-heap-size=64m mono app.exe
Defensive patterns
Strategy: validation
Validate before calling
# Parse MONO_GC_PARAMS exactly like the runtime and reject values below the 16 MiB Boehm floor.
python3 - <<'PY'
import os, re
params = os.environ.get('MONO_GC_PARAMS', '')
for tok in params.split(','):
m = re.match(r'^max-heap-size=(.*)$', tok.strip())
if not m: continue
val = m.group(1)
if not re.match(r'^\d+[kKmMgG]?$', val):
continue
suffix, shift = val[-1].lower(), 0
num = int(re.match(r'^\d+', val).group(0))
if suffix in 'kmg': shift = {'k':1,'m':2,'g':3}[suffix] * 10
bytes_ = num << shift
if bytes_ < (16 << 20):
raise SystemExit(f'ERROR: max-heap-size={val} ({bytes_} bytes) < Boehm floor 16MiB; use >=16m')
print('MONO_GC_PARAMS OK')
PY
exec mono "$@" Prevention
- Remember the Boehm floor is 16 MiB and suffixes are k/m/g (KiB/MiB/GiB); a bare number is bytes.
- Validate MONO_GC_PARAMS in your launch wrapper before starting Mono so a sub-floor value fails with a clear message instead of exit(1).
- If you need a smaller heap, do not use the Boehm GC; switch to sgen.
- Document the unit convention next to any heap-size configuration in your deployment templates.
When it happens
Trigger: Launching a Mono runtime built with the Boehm GC (HAVE_BOEHM_GC) with MONO_GC_PARAMS containing `max-heap-size=<n>` where <n> resolves to fewer than 16 MiB after suffix expansion, e.g. max-heap-size=8, max-heap-size=15m, max-heap-size=1000k. mono_gc_base_init() runs once at startup; the MIN_BOEHM_MAX_HEAP_SIZE floor is hardcoded at boehm-gc.c:52-53.
Common situations: Operator sets a heap cap to constrain memory and picks a value below the Boehm floor (16m); confusing suffixes (assuming m=KB or that the number is already in MB when suffixless means bytes); copying an sgen-style value into a Boehm build; container memory-constraint scripts that autogenerate small max-heap-size values; typo like max-heap-size=1m expecting 1 GB.
Related errors
- max-heap-size must be an integer.\n
- Unrecognized asset behavior:${asset.behavior}, for asset ${a
- Failed to load ICU data
- Unexpected behavior ${asset.behavior} of asset ${asset.name}
- NodeJS at '${process.execPath}' has too low version '${proce
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/a55824b6902fa31d.
Report an issue: GitHub.