dotnet/runtime · critical
max-heap-size must be an integer.\n
Error message
max-heap-size must be an integer.\n
What it means
Emitted during Mono Boehm GC init in mono_gc_base_init (boehm-gc.c:176) when a `max-heap-size=` token is present but mono_gc_parse_environment_string_extract_number returns FALSE. That helper fails on an empty string, a non-digit last character that is not a valid k/m/g suffix, strtol overflow (ERANGE), or a suffix form with trailing characters after the suffix. On failure the runtime prints 'max-heap-size must be an integer.' and calls exit(1), killing the process at GC init before managed code runs.
Source
Thrown at src/mono/mono/metadata/boehm-gc.c:176
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);
*/
}
}
g_free (env);
g_strfreev (opts);
}View on GitHub (pinned to 290d5ab72c)
Solutions
- Use a plain integer or a single k/m/g suffix: MONO_GC_PARAMS=max-heap-size=256m (not 256mb / 256MB).
- Remove any trailing unit characters, spaces, or quotes; the token after '=' must be digits optionally followed by exactly one of k/m/g (case-insensitive).
- For very large values, drop down a suffix to avoid size_t overflow (e.g. prefer 4g over 4294967296).
- Validate MONO_GC_PARAMS in a launch wrapper (parse the same way) before starting Mono so misconfigurations fail with your own message.
- Inspect for accidental empty assignments from CI/CD templating (e.g. MONO_GC_PARAMS=max-heap-size=$HEAP where $HEAP is unset).
Example fix
# before $ MONO_GC_PARAMS=max-heap-size=256mb mono app.exe # 'mb' is invalid max-heap-size must be an integer. # (process exits) # after $ MONO_GC_PARAMS=max-heap-size=256m mono app.exe
Defensive patterns
Strategy: validation
Validate before calling
# Validate max-heap-size syntax (digits + optional single k/m/g) exactly as mono_gc_parse_environment_string_extract_number does.
python3 - <<'PY'
import os, re
for tok in os.environ.get('MONO_GC_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):
raise SystemExit(f'ERROR: max-heap-size={val!r} is not <integer>[k|m|g]; use e.g. 256m')
print('MONO_GC_PARAMS OK')
PY
exec mono "$@" Prevention
- Use exactly one suffix letter — k, m, or g (case-insensitive). 'mb', 'MB', 'gb', 'b' are all invalid.
- Never leave the value empty; guard against unset template variables (max-heap-size=$HEAP with HE unset).
- For very large heaps prefer a suffix (4g) over a huge bare number to avoid size_t overflow (ERANGE).
- Validate MONO_GC_PARAMS in a pre-launch wrapper so misconfigurations surface as your own error, not an exit(1) at GC init.
When it happens
Trigger: Boehm-GC Mono runtime started with MONO_GC_PARAMS=max-heap-size=<bad>, where <bad> is empty (max-heap-size=), non-numeric (max-heap-size=abc), contains trailing garbage (max-heap-size=64mb, max-heap-size=10x), uses an unsupported suffix (max-heap-size=64b), or overflows size_t. The parser in parse.c:28 rejects all of these and returns FALSE, tripping the else-branch fprintf at boehm-gc.c:176.
Common situations: Writing 'mb'/'MB' instead of 'm' (the helper only accepts a single m/M/k/K/g/G); a stray space or unit; an empty value from a templated env file; copy-pasting a Java -Xmx style value; value too large for the platform size_t (ERANGE); shell-quoting dropping the number.
Related errors
- max-heap-size must be at least %dMb.\n
- Unrecognized asset behavior:${asset.behavior}, for asset ${a
- .NET runtime has failed to start, because too much memory wa
- invariant globalization mode is inactive and no ICU data arc
- Invalid jsThreadBlockingMode
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/123096d03cf7da40.
Report an issue: GitHub.