{"record":{"id":"4fcd34045c2f9ee3","repo":"Tyrrrz/YoutubeDownloader","slug":"invalid-json-for-type-typetoconvert-fullname","errorCode":null,"errorMessage":"Invalid JSON for type '{typeToConvert.FullName}'.","messagePattern":"Invalid JSON for type '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"YoutubeDownloader/Services/SettingsService.cs","lineNumber":111,"sourceCode":"            {\n                while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)\n                {\n                    if (\n                        reader.TokenType == JsonTokenType.PropertyName\n                        && reader.GetString() == \"Name\"\n                        && reader.Read()\n                        && reader.TokenType == JsonTokenType.String\n                    )\n                    {\n                        var name = reader.GetString();\n                        if (!string.IsNullOrWhiteSpace(name))\n                            result = new Container(name);\n                    }\n                }\n            }\n\n            return result\n                ?? throw new InvalidOperationException(\n                    $\"Invalid JSON for type '{typeToConvert.FullName}'.\"\n                );\n        }\n\n        public override void Write(\n            Utf8JsonWriter writer,\n            Container value,\n            JsonSerializerOptions options\n        )\n        {\n            writer.WriteStartObject();\n            writer.WriteString(\"Name\", value.Name);\n            writer.WriteEndObject();\n        }\n    }\n}\n\npublic partial class SettingsService","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/Tyrrrz/YoutubeDownloader/blob/bbcff039515a2ac985e3769f0243a58645a52b28/YoutubeDownloader/Services/SettingsService.cs#L93-L129","documentation":"Thrown by the custom ContainerJsonConverter.Read while deserializing the LastContainer setting. The converter expects a JSON object of exactly {\"Name\":\"<non-empty>\"} and treats anything else - null, a bare string, an object without a Name property, an empty name, or a Name in a different case - as invalid, because Container (YoutubeExplode) has no implicit default.","triggerScenarios":"The settings file (StartOptions.Current.SettingsPath) holds a LastContainer value that isn't {\"Name\":\"mp4\"} - e.g. null, \"mp4\", {}, {\"Container\":\"mp4\"}, or {\"name\":\"mp4\"}. The property comparison reader.GetString() == \"Name\" at line 98 is case-sensitive, so camelCase/lowercase keys fail. Reached whenever settings are loaded/deserialized.","commonSituations":"Upgrading from an older app version that serialized Container differently (e.g. as a plain string or under a different key); hand-editing the settings file; partial-write corruption; a casing change in the serialized form; schema drift after a YoutubeExplode version bump.","solutions":["Delete or reset the settings file so it regenerates with the default (Container.Mp4).","Correct the offending JSON to the canonical shape {\"Name\":\"mp4\"} (or webm/mp3/etc.).","Make the converter tolerant: return a default on null/empty, accept a bare string for backward compat, and use case-insensitive property matching so legacy/corrupt values don't crash settings load."],"exampleFix":"// before: any deviation from {\"Name\":\"...\"} throws and blocks settings load\nreturn result\n    ?? throw new InvalidOperationException($\"Invalid JSON for type '{typeToConvert.FullName}'.\");\n\n// after: fall back to a sensible default instead of throwing\nreturn result ?? Container.Mp4;","handlingStrategy":"try-catch","validationCode":"using var doc = JsonDocument.Parse(File.ReadAllText(settingsPath));\n\nif (doc.RootElement.TryGetProperty(nameof(SettingsService.LastContainer), out var c)\n    && (c.ValueKind != JsonValueKind.Object\n        || !c.TryGetProperty(\"Name\", out var n)\n        || n.ValueKind != JsonValueKind.String\n        || string.IsNullOrWhiteSpace(n.GetString())))\n{\n    // reset LastContainer to the default before deserializing\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    settings.Load();\n}\ncatch (InvalidOperationException ex) when (ex.Message.StartsWith(\"Invalid JSON for type\"))\n{\n    File.Move(settingsPath, settingsPath + \".bak\", overwrite: true);\n    settings.Load(); // regenerates with defaults\n}","preventionTips":["Make the converter resilient: return a default on null/empty, accept a bare string, and match the Name property case-insensitively.","Wrap settings load in try/catch that backs up and resets the file on failure.","Write settings atomically (temp file + rename) to avoid partial-write corruption.","Add a settings migration step on version upgrade."],"tags":["json","settings","serialization","system-text-json","migration","configuration"],"backgroundTag":null,"analyzedSha":"bbcff039515a2ac985e3769f0243a58645a52b28","analyzedAt":"2026-08-13T14:28:37.801Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}