dotnet/runtime · warning

Precise stack mark not supported - disabling.\n

Error message

Precise stack mark not supported - disabling.\n

What it means

During SGen's thread scan (sgen_client_scan_thread_data), a precise stack mark requires mono_gc_get_gc_callbacks()->thread_mark_func to be registered. When a thread is on the imprecise pass, precise marking was requested, but no thread_mark_func exists, SGen logs this once, sets the static conservative_stack_mark flag to TRUE, and pins the thread stack conservatively. Note sgen_client_init already defaults conservative_stack_mark=TRUE with the comment 'Precise marking is broken on all supported targets. Disable until fixed.', so this message only appears when precise is explicitly requested and unsupported.

Source

Thrown at src/mono/mono/metadata/sgen-mono.c:2128

				 */
				HandleStack *stack = info->client_info.info.handle_stack;
				g_assert (stack == NULL || mono_handle_stack_is_empty (stack));
			}
			continue;
		}

		g_assert (info->client_info.stack_start);
		g_assert (info->client_info.info.stack_end);

		aligned_stack_start = get_aligned_stack_start (info);
		g_assert (info->client_info.suspend_done);
		if (!debug_coop_no_stack_scan) {
			SGEN_LOG (3, "Scanning thread %p, range: %p-%p, size: %" G_GSIZE_FORMAT "d, pinned=%" G_GSIZE_FORMAT "d", info, info->client_info.stack_start, info->client_info.info.stack_end, (char*)info->client_info.info.stack_end - (char*)info->client_info.stack_start, sgen_get_pinned_count ());
			if (mono_gc_get_gc_callbacks ()->thread_mark_func && !conservative_stack_mark) {
				mono_gc_get_gc_callbacks ()->thread_mark_func (info->client_info.runtime_data, (guint8 *)aligned_stack_start, (guint8 *)info->client_info.info.stack_end, precise, &ctx);
			} else if (!precise) {
				if (!conservative_stack_mark) {
					fprintf (stderr, "Precise stack mark not supported - disabling.\n");
					conservative_stack_mark = TRUE;
				}
				//FIXME we should eventually use the new stack_mark from coop
				sgen_conservatively_pin_objects_from ((void **)aligned_stack_start, (void **)info->client_info.info.stack_end, start_nursery, end_nursery, PIN_TYPE_STACK);
			}

			if (!precise) {
				sgen_conservatively_pin_objects_from ((void**)&info->client_info.ctx, (void**)(&info->client_info.ctx + 1),
					start_nursery, end_nursery, PIN_TYPE_STACK);

				{
					// This is used on Coop GC for platforms where we cannot get the data for individual registers.
					// We force a spill of all registers into the stack and pass a chunk of data into sgen.
					//FIXME under coop, for now, what we need to ensure is that we scan any extra memory from info->client_info.info.stack_end to stack_mark
					MonoThreadUnwindState *state = &info->client_info.info.thread_saved_state [SELF_SUSPEND_STATE_INDEX];
					if (state && state->gc_stackdata) {
						sgen_conservatively_pin_objects_from ((void **)state->gc_stackdata, (void**)((char*)state->gc_stackdata + state->gc_stackdata_size),
							start_nursery, end_nursery, PIN_TYPE_STACK);

View on GitHub (pinned to 60108ba66e)

Solutions

  1. Remove 'stack-mark=precise' from MONO_GC_PARAMS and rely on the default conservative marking
  2. Use a runtime/platform build that registers thread_mark_func (a cooperative-GC-enabled build) if precise marking is required
  3. Treat the message as informational: GC correctness is preserved via the automatic conservative fallback, only precision/pinning behavior changes

Example fix

# before
export MONO_GC_PARAMS=stack-mark=precise

# after
# omit the option; default conservative stack marking is used
export MONO_GC_PARAMS=
Defensive patterns

Strategy: fallback

Validate before calling

// After the runtime is initialized, query whether precise marking actually took effect.
// mono_gc_precise_stack_mark_enabled() returns !conservative_stack_mark (gc-internals.h:363).
#include <mono/metadata/mono-gc.h>
gboolean want_precise = g_getenv ("MONO_GC_PARAMS") != NULL; // your own logic
if (want_precise && !mono_gc_precise_stack_mark_enabled ()) {
    g_print ("Precise stack marking is not available on this platform/runtime; "
             "GC will run in conservative mode.\n");
}

Prevention

When it happens

Trigger: Setting MONO_GC_PARAMS=stack-mark=precise on a runtime or platform that does not register a GC thread_mark_func (i.e. without the cooperative GC's thread-mark callback). Emitted at most once per process because it flips the global conservative_stack_mark flag on first occurrence.

Common situations: Opting into precise stack marking to reduce false pinning on a platform where it isn't implemented; embedding Mono in a custom host that does not install the GC thread-mark callback; running on an older/newer runtime whose platform support for precise marking changed.

Related errors


AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10). Data as JSON: /api/errors/0cf1e0ffa274fee8. Report an issue: GitHub.