diff --git a/StabilityMatrix.Core/Models/Api/CivitImage.cs b/StabilityMatrix.Core/Models/Api/CivitImage.cs index c29e3baca..e018f5c68 100644 --- a/StabilityMatrix.Core/Models/Api/CivitImage.cs +++ b/StabilityMatrix.Core/Models/Api/CivitImage.cs @@ -11,10 +11,10 @@ public class CivitImage public int? NsfwLevel { get; set; } [JsonPropertyName("width")] - public int Width { get; set; } + public int? Width { get; set; } [JsonPropertyName("height")] - public int Height { get; set; } + public int? Height { get; set; } [JsonPropertyName("hash")] public string Hash { get; set; } diff --git a/StabilityMatrix.Core/Models/PackageModification/DownloadCivitWorkflowStep.cs b/StabilityMatrix.Core/Models/PackageModification/DownloadCivitWorkflowStep.cs index 3bffd45eb..ac06e9ad9 100644 --- a/StabilityMatrix.Core/Models/PackageModification/DownloadCivitWorkflowStep.cs +++ b/StabilityMatrix.Core/Models/PackageModification/DownloadCivitWorkflowStep.cs @@ -285,8 +285,8 @@ private WorkflowMetadata CreateMetadata(string name, bool isMultiple) new OpenArtThumbnail { Url = new Uri(thumbnailUrl), - Width = thumbnail!.Width, - Height = thumbnail.Height, + Width = thumbnail!.Width ?? 0, + Height = thumbnail.Height ?? 0, }, ], }, diff --git a/StabilityMatrix.Tests/Core/CivitImageTests.cs b/StabilityMatrix.Tests/Core/CivitImageTests.cs new file mode 100644 index 000000000..31a66cdae --- /dev/null +++ b/StabilityMatrix.Tests/Core/CivitImageTests.cs @@ -0,0 +1,78 @@ +using System.Text.Json; +using StabilityMatrix.Core.Models.Api; + +namespace StabilityMatrix.Tests.Core; + +[TestClass] +public class CivitImageTests +{ + [TestMethod] + public void TestDeserialize_CivitImageWithNullDimensions_ShouldBeNull() + { + // CivitAI sends null width/height for some images (observed live 2026-11-06, issue #1792) + const string json = """ + { + "url": "https://image.civitai.com/example.jpeg", + "nsfwLevel": 8, + "width": null, + "height": null, + "hash": "abc", + "type": "image" + } + """; + + var result = JsonSerializer.Deserialize(json); + + Assert.IsNotNull(result); + Assert.IsNull(result.Width); + Assert.IsNull(result.Height); + Assert.AreEqual("https://image.civitai.com/example.jpeg", result.Url); + } + + [TestMethod] + public void TestDeserialize_CivitImageWithDimensions_ShouldReadValues() + { + const string json = """ + { "url": "https://image.civitai.com/example.jpeg", "width": 832, "height": 1216 } + """; + + var result = JsonSerializer.Deserialize(json); + + Assert.IsNotNull(result); + Assert.AreEqual(832, result.Width); + Assert.AreEqual(1216, result.Height); + } + + [TestMethod] + public void TestDeserialize_ModelsResponseWithNullImageDimensions_ShouldKeepAllItems() + { + // One image with null dimensions used to fail the whole page of results + const string json = """ + { + "items": [ + { + "id": 1, + "name": "First", + "modelVersions": [ + { "id": 10, "name": "v1", "images": [ { "url": "https://a", "width": 512, "height": 512 } ] } + ] + }, + { + "id": 2, + "name": "Second", + "modelVersions": [ + { "id": 20, "name": "v1", "images": [ { "url": "https://b", "width": null, "height": null } ] } + ] + } + ], + "metadata": {} + } + """; + + var result = JsonSerializer.Deserialize(json); + + Assert.IsNotNull(result?.Items); + Assert.AreEqual(2, result.Items.Count); + Assert.IsNull(result.Items[1].ModelVersions![0].Images![0].Width); + } +}