Tyrrrz/YoutubeDownloader · error · InvalidOperationException
Invalid JSON for type '{typeToConvert.FullName}'.
Error message
Invalid JSON for type '{typeToConvert.FullName}'. What it means
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.
Source
Thrown at YoutubeDownloader/Services/SettingsService.cs:111
{
while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
{
if (
reader.TokenType == JsonTokenType.PropertyName
&& reader.GetString() == "Name"
&& reader.Read()
&& reader.TokenType == JsonTokenType.String
)
{
var name = reader.GetString();
if (!string.IsNullOrWhiteSpace(name))
result = new Container(name);
}
}
}
return result
?? throw new InvalidOperationException(
$"Invalid JSON for type '{typeToConvert.FullName}'."
);
}
public override void Write(
Utf8JsonWriter writer,
Container value,
JsonSerializerOptions options
)
{
writer.WriteStartObject();
writer.WriteString("Name", value.Name);
writer.WriteEndObject();
}
}
}
public partial class SettingsServiceView on GitHub (pinned to bbcff03951)
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.
Example fix
// before: any deviation from {"Name":"..."} throws and blocks settings load
return result
?? throw new InvalidOperationException($"Invalid JSON for type '{typeToConvert.FullName}'.");
// after: fall back to a sensible default instead of throwing
return result ?? Container.Mp4; Defensive patterns
Strategy: try-catch
Validate before calling
using var doc = JsonDocument.Parse(File.ReadAllText(settingsPath));
if (doc.RootElement.TryGetProperty(nameof(SettingsService.LastContainer), out var c)
&& (c.ValueKind != JsonValueKind.Object
|| !c.TryGetProperty("Name", out var n)
|| n.ValueKind != JsonValueKind.String
|| string.IsNullOrWhiteSpace(n.GetString())))
{
// reset LastContainer to the default before deserializing
} Try / catch
try
{
settings.Load();
}
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Invalid JSON for type"))
{
File.Move(settingsPath, settingsPath + ".bak", overwrite: true);
settings.Load(); // regenerates with defaults
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
AI-assisted analysis of Tyrrrz/YoutubeDownloader@bbcff03951 (2026-08-13).
Data as JSON: /api/errors/4fcd34045c2f9ee3.
Report an issue: GitHub.