dotnet/maui · error · InvalidOperationException

AppLinkEntry Thumbnail must be set to a valid source

Error message

AppLinkEntry Thumbnail must be set to a valid source

What it means

When building a CSSearchableItemAttributeSet for Spotlight indexing, iOSAppLinks optionally attaches a thumbnail image. If the AppLinkEntry.Thumbnail ImageSource is non-null but GetNativeImageAsync() resolves to a null UIImage (the source could not be loaded/decoded), the code throws InvalidOperationException because attaching a null thumbnail would corrupt the Spotlight entry.

Source

Thrown at src/Compatibility/Core/src/iOS/iOSAppLinks.cs:118

		static async Task<CSSearchableItemAttributeSet> GetAttributeSet(IAppLinkEntry deepLinkUri, string contentType, string id)
		{
#pragma warning disable CA1416, CA1422  // TODO: 'CSSearchableItemAttributeSet' is unsupported on: 'ios' 14.0 and later
			var searchableAttributeSet = new CSSearchableItemAttributeSet(contentType)
			{
				RelatedUniqueIdentifier = id,
				Title = deepLinkUri.Title,
				ContentDescription = deepLinkUri.Description,
				Url = new NSUrl(deepLinkUri.AppLinkUri.ToString())
			};
#pragma warning restore CA1416, CA1422

			if (deepLinkUri.Thumbnail != null)
			{
				using (var uiimage = await deepLinkUri.Thumbnail.GetNativeImageAsync())
				{
					if (uiimage == null)
						throw new InvalidOperationException("AppLinkEntry Thumbnail must be set to a valid source");

					searchableAttributeSet.ThumbnailData = uiimage.AsPNG();
				}
			}

			return searchableAttributeSet;
		}

		static NSMutableDictionary GetUserInfoForActivity(IAppLinkEntry deepLinkUri)
		{
			//this info will only appear if not from a spotlight search
			var info = new NSMutableDictionary();
			info.Add(new NSString("link"), new NSString(deepLinkUri.AppLinkUri.ToString()));
			foreach (var item in deepLinkUri.KeyValues)
				info.Add(new NSString(item.Key), new NSString(item.Value));
			return info;
		}

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Verify the thumbnail ImageSource resolves to a real, decodable image before registering the link — test GetNativeImageAsync separately.
  2. For FileImageSource, confirm the file exists in the app bundle with `File.Exists(imageSource.File)`.
  3. For UriImageSource, validate the URL is reachable and returns image content before passing it as a Thumbnail.
  4. If the thumbnail is optional, catch the exception and re-register without a Thumbnail rather than failing the whole registration.

Example fix

// before
entry.Thumbnail = ImageSource.FromFile("missing_icon.png");
Application.Current.AppLinks.RegisterLink(entry);

// after
var thumbPath = "icon.png";
if (File.Exists(thumbPath))
    entry.Thumbnail = ImageSource.FromFile(thumbPath);
Application.Current.AppLinks.RegisterLink(entry);
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate thumbnail source before registration
if (entry.Thumbnail is FileImageSource fis && !File.Exists(fis.File))
    entry.Thumbnail = null; // drop invalid thumbnail
if (entry.Thumbnail is UriImageSource uis && !Uri.IsWellFormedUriString(uis.Uri?.ToString() ?? "", UriKind.Absolute))
    entry.Thumbnail = null;
Application.Current.AppLinks.RegisterLink(entry);

Try / catch

try
{
    Application.Current.AppLinks.RegisterLink(entry);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Thumbnail"))
{
    // Retry without a thumbnail
    entry.Thumbnail = null;
    Application.Current.AppLinks.RegisterLink(entry);
}

Prevention

When it happens

Trigger: An AppLinkEntry with Thumbnail set to a FileImageSource pointing to a missing file, a UriImageSource pointing to a broken/unreachable URL, or a StreamImageSource that yields an empty or undecodable stream. The Thumbnail property is non-null so the code enters the loading block, but GetNativeImageAsync returns null.

Common situations: Bundled asset paths that changed between versions. Remote thumbnail URLs that 404 or return non-image content. StreamImageSource from a disposed or empty stream. Platform-specific asset naming mismatches (e.g., missing @2x suffix or wrong extension).

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/0a4749bb964cbb35. Report an issue: GitHub.