{"record":{"id":"a55824b6902fa31d","repo":"dotnet/runtime","slug":"max-heap-size-must-be-at-least-dmb-n","errorCode":null,"errorMessage":"max-heap-size must be at least %dMb.\\n","messagePattern":"max-heap-size must be at least (.+?)Mb\\.\\\\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/mono/mono/metadata/boehm-gc.c","lineNumber":171,"sourceCode":"\n\tGC_set_warn_proc (mono_gc_warning);\n\tGC_set_finalize_on_demand (1);\n\tGC_set_finalizer_notifier(mono_gc_finalize_notify);\n\n\tGC_init_gcj_malloc (5, NULL);\n\tGC_allow_register_threads ();\n\n\tif ((env = g_getenv (\"MONO_GC_PARAMS\"))) {\n\t\tchar **ptr, **opts = g_strsplit (env, \",\", -1);\n\t\tfor (ptr = opts; *ptr; ++ptr) {\n\t\t\tchar *opt = *ptr;\n\t\t\tif (g_str_has_prefix (opt, \"max-heap-size=\")) {\n\t\t\t\tsize_t max_heap;\n\n\t\t\t\topt = strchr (opt, '=') + 1;\n\t\t\t\tif (*opt && mono_gc_parse_environment_string_extract_number (opt, &max_heap)) {\n\t\t\t\t\tif (max_heap < MIN_BOEHM_MAX_HEAP_SIZE) {\n\t\t\t\t\t\tfprintf (stderr, \"max-heap-size must be at least %dMb.\\n\", MIN_BOEHM_MAX_HEAP_SIZE_IN_MB);\n\t\t\t\t\t\texit (1);\n\t\t\t\t\t}\n\t\t\t\t\tGC_set_max_heap_size (max_heap);\n\t\t\t\t} else {\n\t\t\t\t\tfprintf (stderr, \"max-heap-size must be an integer.\\n\");\n\t\t\t\t\texit (1);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t} else if (g_str_has_prefix (opt, \"toggleref-test\")) {\n\t\t\t\tregister_test_toggleref_callback ();\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\t/* Could be a parameter for sgen */\n\t\t\t\t/*\n\t\t\t\tfprintf (stderr, \"MONO_GC_PARAMS must be a comma-delimited list of one or more of the following:\\n\");\n\t\t\t\tfprintf (stderr, \"  max-heap-size=N (where N is an integer, possibly with a k, m or a g suffix)\\n\");\n\t\t\t\texit (1);\n\t\t\t\t*/","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/dotnet/runtime/blob/290d5ab72cc1102813fbc0406fb186ceadabc340/src/mono/mono/metadata/boehm-gc.c#L153-L189","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\n$ MONO_GC_PARAMS=max-heap-size=8m mono app.exe\nmax-heap-size must be at least 16Mb.\n# (process exits)\n\n# after\n$ MONO_GC_PARAMS=max-heap-size=64m mono app.exe","handlingStrategy":"validation","validationCode":"# Parse MONO_GC_PARAMS exactly like the runtime and reject values below the 16 MiB Boehm floor.\npython3 - <<'PY'\nimport os, re\nparams = os.environ.get('MONO_GC_PARAMS', '')\nfor tok in params.split(','):\n    m = re.match(r'^max-heap-size=(.*)$', tok.strip())\n    if not m: continue\n    val = m.group(1)\n    if not re.match(r'^\\d+[kKmMgG]?$', val):\n        continue\n    suffix, shift = val[-1].lower(), 0\n    num = int(re.match(r'^\\d+', val).group(0))\n    if suffix in 'kmg': shift = {'k':1,'m':2,'g':3}[suffix] * 10\n    bytes_ = num << shift\n    if bytes_ < (16 << 20):\n        raise SystemExit(f'ERROR: max-heap-size={val} ({bytes_} bytes) < Boehm floor 16MiB; use >=16m')\nprint('MONO_GC_PARAMS OK')\nPY\nexec mono \"$@\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["mono","boehm-gc","garbage-collector","environment-variable","mono-gc-params","startup"],"analyzedSha":"290d5ab72cc1102813fbc0406fb186ceadabc340","analyzedAt":"2026-08-06T19:57:01.276Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}