dotnet/runtime · warning
mono/marshal: SafeHandles missing MANAGED_CONV_RESULT\n
Error message
mono/marshal: SafeHandles missing MANAGED_CONV_RESULT\n
What it means
Third unimplemented branch in emit_marshal_safehandle_ilgen: MARSHAL_ACTION_MANAGED_CONV_RESULT covers the case where a reverse P/Invoke (native->managed) managed method returns a SafeHandle that must be converted to a native handle for the caller. Mono prints this to stderr and emits nothing, so the return-value conversion is missing.
Source
Thrown at src/mono/mono/component/marshal-ilgen.c:2046
/* Set the return.handle to the value, am using ldflda, not sure if thats a good idea */
cb_to_mono->methodBuilder.emit_ldloc (mb, 3);
cb_to_mono->methodBuilder.emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle));
cb_to_mono->methodBuilder.emit_ldloc (mb, intptr_handle_slot);
cb_to_mono->methodBuilder.emit_byte (mb, CEE_STIND_I);
break;
}
case MARSHAL_ACTION_MANAGED_CONV_IN:
fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_IN\n");
break;
case MARSHAL_ACTION_MANAGED_CONV_OUT:
fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_OUT\n");
break;
case MARSHAL_ACTION_MANAGED_CONV_RESULT:
fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_RESULT\n");
break;
default:
printf ("Unhandled case for MarshalAction: %d\n", action);
}
return conv_arg;
}
static int
emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
MonoMarshalSpec *spec, int conv_arg,
MonoType **conv_arg_type, MarshalAction action)
{
MonoMethodBuilder *mb = m->mb;
MonoType *int_type = cb_to_mono->get_int_type ();
switch (action){
case MARSHAL_ACTION_CONV_IN: {
conv_arg = cb_to_mono->methodBuilder.add_local (mb, int_type);View on GitHub (pinned to 60108ba66e)
Solutions
- Change the managed callback's return type from SafeHandle to IntPtr, returning handle.DangerousGetHandle(), and let the native caller treat it as a raw handle.
- Return an integer id and expose a separate managed API to resolve it to a SafeHandle on demand.
- Keep all SafeHandle lifetime inside managed code and never return one across a reverse-P/Invoke boundary.
- Target a runtime that implements MANAGED_CONV_RESULT for SafeHandle.
Example fix
// before public delegate SafeFileHandle OpenCallback(string path); // after public delegate IntPtr OpenCallback(string path); // managed helper wraps the returned IntPtr into a SafeFileHandle when needed
Defensive patterns
Strategy: validation
Validate before calling
// Flag reverse-P/Invoke delegates that return SafeHandle (Mono MANAGED_CONV_RESULT unsupported).
static IEnumerable<MethodInfo> CheckReturningSafeHandles(Assembly asm) {
foreach (var t in asm.GetTypes())
foreach (var m in t.GetMethods(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance)) {
if (m.GetCustomAttribute<UnmanagedFunctionPointerAttribute>() == null) continue;
if (typeof(SafeHandle).IsAssignableFrom(m.ReturnType))
yield return m;
}
} Prevention
- Return IntPtr, not SafeHandle, from delegates called by native code.
- Expose a managed helper to wrap the returned handle later.
- Scan interop assemblies for SafeHandle-returning reverse delegates at build time.
- Target a runtime with full SafeHandle managed-conv support if unavoidable.
When it happens
Trigger: A managed delegate invoked from native code returns a SafeHandle; the marshaller needs to emit IL extracting/returning the raw handle but this case is a no-op.
Common situations: Reverse P/Invoke whose managed handler returns a SafeHandle (e.g. returning a file/socket handle to native); COM interop with SafeHandle return values on Mono; code that behaves on CoreCLR but hits the unimplemented Mono path.
Related errors
- mono/marshal: SafeHandles missing MANAGED_CONV_IN\n
- mono/marshal: SafeHandles missing MANAGED_CONV_OUT\n
- Unhandled case for MarshalAction: %d\n
- Locale or culture name is null or empty. localeName=${locale
- ${part} not found while looking up ${function_name}
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/9d2e84d0f65fdf87.
Report an issue: GitHub.