dotnet/runtime · error
max-heap-size must be an integer.\n
Error message
max-heap-size must be an integer.\n
What it means
Emitted by Mono's Boehm GC backend in mono_gc_base_init while parsing the MONO_GC_PARAMS environment variable. The 'max-heap-size=' value is parsed with mono_gc_parse_environment_string_extract_number, which accepts only digits with an optional single trailing k/m/g suffix. When parsing fails, the runtime prints this message and calls exit(1), aborting startup before the app runs. Note this fatal-exit path is specific to Boehm; SGen has an analogous check (sgen-gc.c:3561) that only logs via sgen_env_var_error and continues.
Solutions
- Set the value to a plain integer or integer plus a single k/m/g suffix, e.g. MONO_GC_PARAMS=max-heap-size=512m
- If the value is interpolated from another variable, guard against emptiness, e.g. ${HEAP:-256m}
- Confirm the resolved value is >= 16 MB to avoid the separate 'must be at least 16Mb' fatal check
- If you intended to configure SGen instead of Boehm, verify which collector is active; this exit(1) only fires under Boehm
Example fix
# before
export MONO_GC_PARAMS=max-heap-size=$HEAP # aborts when HEAP is unset/empty
# after
export MONO_GC_PARAMS=max-heap-size=${HEAP:-512m} Defensive patterns
Strategy: validation
Validate before calling
# Validate MONO_GC_PARAMS max-heap-size BEFORE launching mono.
# Accepts digits with an optional single trailing k/m/g; rejects empty/garbage.
validate_max_heap () {
local val="$1"
if [[ ! "$val" =~ ^[0-9]+[kKmMgG]?$ ]]; then
echo "reject: '$val' is not an integer (optional k/m/g suffix)" >&2
return 1
fi
# numeric part must be >= 16 (MB floor) when given as plain megabytes
local num="${val%[kKmMgG]}"
if [[ "$val" =~ [gG]$ ]]; then num=$((num*1024));
elif [[ "$val" =~ [kK]$ ]]; then num=$((num/1024)); fi
(( num >= 16 )) || { echo "reject: below 16MB floor" >&2; return 1; }
return 0
}
# usage: validate_max_heap "${HEAP:-}" && export MONO_GC_PARAMS=max-heap-size=$HEAP Prevention
- Never interpolate an unguarded variable into MONO_GC_PARAMS; default it, e.g. ${HEAP:-512m}
- Treat the value as a pure integer plus at most one k/m/g letter (lowercase preferred); 'mb', 'mib', spaces, and quotes are invalid
- Remember the floor is 16 MB on Boehm and the failure mode is process exit(1), not an exception
- In launch scripts, run the validator above before exec'ing the mono runtime so misconfiguration fails fast with a clear message
When it happens
Trigger: Setting MONO_GC_PARAMS with 'max-heap-size=<X>' where <X> is empty, contains non-digit characters (other than a single trailing k/m/g), has trailing garbage after the suffix (e.g. '512mib'), or overflows strtol/size_t. The value is also rejected with a different message if below MIN_BOEHM_MAX_HEAP_SIZE_IN_MB (16 MB).
Common situations: Shell scripts that interpolate an unset variable (max-heap-size=$HEAP with HEAP empty), copy-pasting documentation that spells units as 'mb' instead of 'm', a stray comma or quote inside the value, or a typo such as 'max-heap-size=512MB'. Occurs on startup of any Mono process using the Boehm collector.
Related errors
- max-heap-size must be at least %dMb.\n
- Precise stack mark not supported - disabling.\n
- Warning: Could not open bridge dump file
- Can't use moduleFactory callback of createDotnetRuntime…
- Invalid config, resources is not set
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/123096d03cf7da40.
Report an issue: GitHub.
Appendix: 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 60108ba66e)