{"record":{"id":"0a4749bb964cbb35","repo":"dotnet/maui","slug":"applinkentry-thumbnail-must-be-set-to-a-valid-sour","errorCode":null,"errorMessage":"AppLinkEntry Thumbnail must be set to a valid source","messagePattern":"AppLinkEntry Thumbnail must be set to a valid source","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Compatibility/Core/src/iOS/iOSAppLinks.cs","lineNumber":118,"sourceCode":"\n\t\tstatic async Task<CSSearchableItemAttributeSet> GetAttributeSet(IAppLinkEntry deepLinkUri, string contentType, string id)\n\t\t{\n#pragma warning disable CA1416, CA1422  // TODO: 'CSSearchableItemAttributeSet' is unsupported on: 'ios' 14.0 and later\n\t\t\tvar searchableAttributeSet = new CSSearchableItemAttributeSet(contentType)\n\t\t\t{\n\t\t\t\tRelatedUniqueIdentifier = id,\n\t\t\t\tTitle = deepLinkUri.Title,\n\t\t\t\tContentDescription = deepLinkUri.Description,\n\t\t\t\tUrl = new NSUrl(deepLinkUri.AppLinkUri.ToString())\n\t\t\t};\n#pragma warning restore CA1416, CA1422\n\n\t\t\tif (deepLinkUri.Thumbnail != null)\n\t\t\t{\n\t\t\t\tusing (var uiimage = await deepLinkUri.Thumbnail.GetNativeImageAsync())\n\t\t\t\t{\n\t\t\t\t\tif (uiimage == null)\n\t\t\t\t\t\tthrow new InvalidOperationException(\"AppLinkEntry Thumbnail must be set to a valid source\");\n\n\t\t\t\t\tsearchableAttributeSet.ThumbnailData = uiimage.AsPNG();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn searchableAttributeSet;\n\t\t}\n\n\t\tstatic NSMutableDictionary GetUserInfoForActivity(IAppLinkEntry deepLinkUri)\n\t\t{\n\t\t\t//this info will only appear if not from a spotlight search\n\t\t\tvar info = new NSMutableDictionary();\n\t\t\tinfo.Add(new NSString(\"link\"), new NSString(deepLinkUri.AppLinkUri.ToString()));\n\t\t\tforeach (var item in deepLinkUri.KeyValues)\n\t\t\t\tinfo.Add(new NSString(item.Key), new NSString(item.Value));\n\t\t\treturn info;\n\t\t}\n","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/dotnet/maui/blob/f377ff1c5ee04d334d8a925f50c83a6b7afddf03/src/Compatibility/Core/src/iOS/iOSAppLinks.cs#L100-L136","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Verify the thumbnail ImageSource resolves to a real, decodable image before registering the link — test GetNativeImageAsync separately.","For FileImageSource, confirm the file exists in the app bundle with `File.Exists(imageSource.File)`.","For UriImageSource, validate the URL is reachable and returns image content before passing it as a Thumbnail.","If the thumbnail is optional, catch the exception and re-register without a Thumbnail rather than failing the whole registration."],"exampleFix":"// before\nentry.Thumbnail = ImageSource.FromFile(\"missing_icon.png\");\nApplication.Current.AppLinks.RegisterLink(entry);\n\n// after\nvar thumbPath = \"icon.png\";\nif (File.Exists(thumbPath))\n    entry.Thumbnail = ImageSource.FromFile(thumbPath);\nApplication.Current.AppLinks.RegisterLink(entry);","handlingStrategy":"try-catch","validationCode":"// Validate thumbnail source before registration\nif (entry.Thumbnail is FileImageSource fis && !File.Exists(fis.File))\n    entry.Thumbnail = null; // drop invalid thumbnail\nif (entry.Thumbnail is UriImageSource uis && !Uri.IsWellFormedUriString(uis.Uri?.ToString() ?? \"\", UriKind.Absolute))\n    entry.Thumbnail = null;\nApplication.Current.AppLinks.RegisterLink(entry);","typeGuard":null,"tryCatchPattern":"try\n{\n    Application.Current.AppLinks.RegisterLink(entry);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Thumbnail\"))\n{\n    // Retry without a thumbnail\n    entry.Thumbnail = null;\n    Application.Current.AppLinks.RegisterLink(entry);\n}","preventionTips":["Test FileImageSource paths against the app bundle before using them as thumbnails.","Validate remote thumbnail URLs return image content before indexing.","Treat thumbnails as optional — wrap registration in try-catch and retry without the thumbnail."],"tags":["maui","ios","applinks","core-spotlight","image-source","thumbnail"],"backgroundTag":null,"analyzedSha":"f377ff1c5ee04d334d8a925f50c83a6b7afddf03","analyzedAt":"2026-08-13T14:26:18.069Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}