mgth/LittleBigMouse · error · JsonException
Unterminated border resistance side.
Error message
Unterminated border resistance side.
What it means
After reading the initial token, Read loops through the object's members until it encounters EndObject. If the JSON stream ends (Read returns false) before the closing brace of the border-resistance-side object, the converter throws this JsonException. It indicates the serialized object was never closed.
Solutions
- Validate the JSON file with a parser (e.g. JSON lint) and add the missing closing braces.
- Restore the settings file from backup or delete it so the app recreates defaults.
- Enable atomic writes (write temp file then rename) in whatever code persists these settings to avoid truncation.
- Catch JsonException during load and fall back to a freshly generated default config.
Example fix
// before (truncated)
{ "left": { "resistance": 5
// after
{ "left": { "resistance": 5 } } Defensive patterns
Strategy: try-catch
Validate before calling
// verify JSON is well-formed before deserializing
try { using var _ = System.Text.Json.JsonDocument.Parse(json); }
catch (JsonException) { json = "{}"; /* rebuild defaults */ } Type guard
static bool IsCompleteJson(string s)
{
try { using var _ = System.Text.Json.JsonDocument.Parse(s); return true; }
catch (JsonException) { return false; }
} Try / catch
try
{
dto = JsonSerializer.Deserialize<BorderSideDto>(json, options);
}
catch (JsonException ex) when (ex.Message.Contains("Unterminated"))
{
Log.LogWarning("Settings JSON truncated; regenerating defaults.");
dto = new BorderSideDto();
} Prevention
- Persist settings atomically: write to a temp file then File.Move/replace.
- Never hand-edit config files without re-validating with a JSON parser afterward.
- Keep a known-good backup of the settings file and restore it when parsing fails.
When it happens
Trigger: Deserializing truncated JSON such as {"left": {"resistance": 5 with no closing braces, typically from a partially written or cut-off settings file.
Common situations: Settings file corrupted by an app crash or power loss mid-write, file truncated by sync/disk issues, or manual editing that dropped closing braces.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
AI-assisted analysis of mgth/LittleBigMouse@7a42f01d47 (2026-09-16).
Data as JSON: /api/errors/e31ec4c4235bf139.
Report an issue: GitHub.
Appendix: source
Thrown at LittleBigMouse.Plugins/LittleBigMouse.Plugins.Core/Persistence/BorderSideDtoJsonConverter.cs:79
case nameof(BorderSideDto.MoveBlock):
dto.MoveBlock = ReadNullableBool(ref reader);
break;
case nameof(BorderSideDto.Drag):
dto.Drag = ReadNullableDouble(ref reader);
break;
case nameof(BorderSideDto.DragBlock):
dto.DragBlock = ReadNullableBool(ref reader);
break;
case nameof(BorderSideDto.Sections):
dto.Sections = JsonSerializer.Deserialize<List<BorderSectionDto>>(ref reader, options);
break;
default:
reader.Skip();
break;
}
}
throw new JsonException("Unterminated border resistance side.");
}
public override void Write(Utf8JsonWriter writer, BorderSideDto value, JsonSerializerOptions options)
{
writer.WriteStartObject();
if (value.Move is { } move) writer.WriteNumber(nameof(BorderSideDto.Move), move);
if (value.MoveBlock is { } moveBlock) writer.WriteBoolean(nameof(BorderSideDto.MoveBlock), moveBlock);
if (value.Drag is { } drag) writer.WriteNumber(nameof(BorderSideDto.Drag), drag);
if (value.DragBlock is { } dragBlock) writer.WriteBoolean(nameof(BorderSideDto.DragBlock), dragBlock);
if (value.Sections is { Count: > 0 } sections)
{
writer.WritePropertyName(nameof(BorderSideDto.Sections));
JsonSerializer.Serialize(writer, sections, options);
}
writer.WriteEndObject();View on GitHub (pinned to 7a42f01d47)