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

  1. 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
  2. If the value is interpolated from another variable, guard against emptiness, e.g. ${HEAP:-256m}
  3. Confirm the resolved value is >= 16 MB to avoid the separate 'must be at least 16Mb' fatal check
  4. 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

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


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)