AvaloniaUI/Avalonia · critical · InvalidOperationException

Main activity must implement IActivityResultHandler interfac

Error message

Main activity must implement IActivityResultHandler interface.

What it means

Thrown by AndroidStorageProvider.StartActivity when the host _activity is not an IActivityResultHandler. Storage pickers (file/folder open/save) rely on StartActivityForResult and need the Activity to route OnActivityResult back into Avalonia via the IActivityResultHandler interface; if the host activity doesn't implement it, the result callback cannot be wired.

Source

Thrown at src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs:231

            .PutExtra(Intent.ExtraAllowMultiple, options.AllowMultiple);

        intent = TryAddExtraInitialUri(intent, options.SuggestedStartLocation);

        var pickerIntent = Intent.CreateChooser(intent, options.Title ?? "Select folder");

        var uris = await StartActivity(pickerIntent, false);
        return uris.Select(u => new AndroidStorageFolder(_activity, u, false)).ToArray();
    }

    private async Task<List<AndroidUri>> StartActivity(Intent? pickerIntent, bool singleResult)
    {
        var resultList = new List<AndroidUri>(1);
        var tcs = new TaskCompletionSource<Intent?>();
        var currentRequestCode = PlatformSupport.GetNextRequestCode();

        if (!(_activity is IActivityResultHandler mainActivity))
        {
            throw new InvalidOperationException("Main activity must implement IActivityResultHandler interface.");
        }

        mainActivity.ActivityResult += OnActivityResult;
        _activity.StartActivityForResult(pickerIntent, currentRequestCode);

        var result = await tcs.Task;

        if (result != null)
        {
            // ClipData first to avoid issue with multiple files selection.
            if (!singleResult && result.ClipData is { } clipData)
            {
                for (var i = 0; i < clipData.ItemCount; i++)
                {
                    var uri = clipData.GetItemAt(i)?.Uri;
                    if (uri != null)
                    {
                        resultList.Add(uri);

View on GitHub (pinned to 11c5427268)

Solutions

  1. Make your host Activity extend AvaloniaMainActivity<TApp> (or AvaloniaFragmentActivity) so it implements IActivityResultHandler.
  2. If you must use a custom base, implement IActivityResultHandler manually and forward OnActivityResult to the ActivityResult event.
  3. Do not call the storage picker before the Activity is fully created/initialized.

Example fix

// before
public class MainActivity : Activity { ... } // not an IActivityResultHandler

// after
public class MainActivity : AvaloniaMainActivity<MyApp> { ... } // implements IActivityResultHandler
Defensive patterns

Strategy: validation

Validate before calling

// confirm the activity can handle results before launching a picker
if (activity is not IActivityResultHandler)
    throw new InvalidOperationException("Host Activity must extend AvaloniaMainActivity/AvaloniaFragmentActivity.");
var files = await storageProvider.OpenFilePickerAsync(options);

Type guard

static bool CanHandleActivityResult(Android.App.Activity a) => a is IActivityResultHandler;

Prevention

When it happens

Trigger: Launching a storage picker (TryGetFileFromPathAsync is not it — these are picker flows like OpenFilePicker/SaveFilePicker) when the application's main Activity does not implement IActivityResultHandler. Typically because the Activity does not extend AvaloniaMainActivity/AvaloniaFragmentActivity, which supply the interface.

Common situations: Custom Activity that extends a plain Android.App.Activity or third-party base instead of Avalonia's; apps integrating Avalonia views inside a non-Avalonia host Activity; libraries that host an AvaloniaView without using the provided base activities.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/87f47d4145fbca3a. Report an issue: GitHub.