XINCGer/Unity3DTraining · error · InvalidJsonException

Invalid first character of token

Error message

Invalid first character of token: {next.Value}

What it means

The internal JsonTokenizer (lexer for JSON used by JsonParser) throws InvalidJsonException when it encounters a character that cannot begin any JSON token (value, string, number, object, array, or literal). Only '-', digits, 't'/'f'/'n', '"', '{', '[' etc. are legal start characters; anything else (e.g. a stray quote, single-quote, or control character) is rejected here.

Solutions

  1. Inspect the character at the reported position and replace it with valid JSON syntax (double quotes, plain ASCII digits/letters).
  2. Sanitize input: replace curly/smart quotes with straight quotes and strip BOM before parsing.
  3. Ensure keys and string values are double-quoted and identifiers like true/false/null are unquoted literals, not bare words with wrong casing.
  4. If the input comes from another system, fix it at the source to emit standards-compliant JSON (test with a strict JSON linter).

Example fix

// before
string json = "{'name': 'x'}"; // single quotes -> InvalidJsonException
var msg = JsonParser.Default.Parse<Message>(json);
// after
string json = "{\"name\": \"x\"}";
var msg = JsonParser.Default.Parse<Message>(json);
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate JSON before parsing
static bool IsLikelyValidJson(string s)
{
    s = s.TrimStart('\uFEFF');
    return s.Length > 0 && (s[0] == '{' || s[0] == '[' || s[0] == '"');
}
// or use a strict parser first: System.Text.Json.JsonDocument.Parse(s)

Try / catch

try
{
    var msg = JsonParser.Default.Parse<T>(json);
}
catch (InvalidJsonException ex)
{
    logger.LogError(ex, "Malformed JSON at token start");
    // report position / sanitize and re-validate
}

Prevention

When it happens

Trigger: Calling JsonParser.Parse<T>(string/json) or JsonFormatter-independent parsing where the input JSON contains a character outside the JSON grammar at a value position — e.g. single-quoted strings ('abc'), trailing commas followed by junk, an unquoted identifier (undefined), or a Unicode character like '\u2019' at a token start.

Common situations: Pasting JSON from a log or email with smart quotes; JavaScript-style input with single quotes or unquoted keys; string encoding issues (BOM or curly quotes) from Windows tools; reading JSON from a file saved with the wrong encoding.

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 XINCGer/Unity3DTraining@016f98412e (2026-09-12). Data as JSON: /api/errors/3a08ac9925520770. Report an issue: GitHub.

Appendix: source

Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/JsonTokenizer.cs:280

                            ConsumeLiteral("false");
                            ValidateAndModifyStateForValue("Invalid state to read a false literal: ");
                            return JsonToken.False;
                        case '-': // Start of a number
                        case '0':
                        case '1':
                        case '2':
                        case '3':
                        case '4':
                        case '5':
                        case '6':
                        case '7':
                        case '8':
                        case '9':
                            double number = ReadNumber(next.Value);
                            ValidateAndModifyStateForValue("Invalid state to read a number token: ");
                            return JsonToken.Value(number);
                        default:
                            throw new InvalidJsonException("Invalid first character of token: " + next.Value);
                    }
                }
            }

            private void ValidateState(State validStates, string errorPrefix)
            {
                if ((validStates & state) == 0)
                {
                    throw reader.CreateException(errorPrefix + state);
                }
            }

            /// <summary>
            /// Reads a string token. It is assumed that the opening " has already been read.
            /// </summary>
            private string ReadString()
            {
                var value = new StringBuilder();

View on GitHub (pinned to 016f98412e)