mgth/LittleBigMouse · error · JsonException

Unexpected token for a border resistance side.

Error message

Unexpected token {reader.TokenType} for a border resistance side.

What it means

BorderSideDtoJsonConverter.Read deserializes a border resistance side from JSON. It accepts a string, number, or start of an object as the value token; any other JSON token (true, false, null, start of array, etc.) makes it throw this JsonException. The library throws it to fail fast on malformed settings JSON rather than silently producing a default BorderSideDto.

Solutions

  1. Open the settings JSON and replace the offending value for the border side with a valid string, number, or object form.
  2. If the value is intentionally unset, use the type's default representation (e.g. a number or empty object) rather than null.
  3. Regenerate the settings file from the app UI so it matches the current schema instead of patching by hand.
  4. Catch JsonException around Deserialize and fall back to default border settings.

Example fix

// before
"borderResistance": { "left": null }
// after
"borderResistance": { "left": 0 }
Defensive patterns

Strategy: validation

Validate before calling

// before deserializing, sanity-check the raw JSON value type for border sides
using var doc = System.Text.Json.JsonDocument.Parse(json);
var side = doc.RootElement.GetProperty("left");
if (side.ValueKind is not (JsonValueKind.String or JsonValueKind.Number or JsonValueKind.Object))
    throw new FormatException($"Border side token {side.ValueKind} is not a valid resistance value.");

Type guard

static bool IsValidBorderSideToken(JsonTokenType t) =>
    t is JsonTokenType.String or JsonTokenType.Number or JsonTokenType.StartObject;

Try / catch

try
{
    var dto = JsonSerializer.Deserialize<BorderSideDto>(json, options);
}
catch (JsonException ex)
{
    Log.LogWarning(ex, "Invalid border resistance side JSON; using defaults.");
    dto = new BorderSideDto();
}

Prevention

When it happens

Trigger: Calling JsonSerializer.Deserialize on JSON where a border-resistance-side property is set to a literal like true, false, null, or an array (e.g. "left": [1,2] or "left": null) instead of a string, number, or object.

Common situations: Hand-edited LittleBigMouse settings files, config generated by a different/older schema version, or a serialization bug writing null for an unconfigured side.

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/7a7c995041ce471b. Report an issue: GitHub.

Appendix: source

Thrown at LittleBigMouse.Plugins/LittleBigMouse.Plugins.Core/Persistence/BorderSideDtoJsonConverter.cs:43

    public override BorderSideDto? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        switch (reader.TokenType)
        {
            case JsonTokenType.Null:
                return null;

            // Legacy: a single resistance governing every crossing.
            case JsonTokenType.Number:
            {
                var value = reader.GetDouble();
                return new BorderSideDto { Move = value, Drag = value };
            }

            case JsonTokenType.StartObject:
                break;

            default:
                throw new JsonException($"Unexpected token {reader.TokenType} for a border resistance side.");
        }

        var dto = new BorderSideDto();

        while (reader.Read())
        {
            if (reader.TokenType == JsonTokenType.EndObject) return dto;
            if (reader.TokenType != JsonTokenType.PropertyName) continue;

            var name = reader.GetString();
            reader.Read();

            switch (name)
            {
                case nameof(BorderSideDto.Move):
                    dto.Move = ReadNullableDouble(ref reader);
                    break;
                case nameof(BorderSideDto.MoveBlock):

View on GitHub (pinned to 7a42f01d47)