{"record":{"id":"1ff9ccfa64b598f5","repo":"github/copilot-sdk","slug":"expected-a-string-token-when-reading-typetoconver","errorCode":null,"errorMessage":"Expected a string token when reading {typeToConvert.Name}, but found {reader.TokenType}.","messagePattern":"Expected a string token when reading (.+?), but found (.+?)\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Types.cs","lineNumber":25,"sourceCode":"using Microsoft.Extensions.Logging;\nusing System;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Diagnostics.CodeAnalysis;\nusing System.Text.Json;\nusing System.Text.Json.Nodes;\nusing System.Text.Json.Serialization;\nusing System.Threading.Tasks;\n\nnamespace GitHub.Copilot;\n\ninternal static class GeneratedStringEnumJson\n{\n    internal static string ReadValue(ref Utf8JsonReader reader, Type typeToConvert)\n    {\n        if (reader.TokenType != JsonTokenType.String)\n        {\n            throw new JsonException($\"Expected a string token when reading {typeToConvert.Name}, but found {reader.TokenType}.\");\n        }\n\n        var value = reader.GetString();\n        if (string.IsNullOrWhiteSpace(value))\n        {\n            throw new JsonException($\"Expected a non-empty string token when reading {typeToConvert.Name}.\");\n        }\n\n        return value!;\n    }\n\n    internal static void WriteValue(Utf8JsonWriter writer, string value, Type typeToConvert)\n    {\n        if (string.IsNullOrWhiteSpace(value))\n        {\n            throw new JsonException($\"Expected a non-empty string value when writing {typeToConvert.Name}.\");\n        }\n","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/dotnet/src/Types.cs#L7-L43","documentation":"GeneratedStringEnumJson.ReadValue is the shared JSON reader for string-backed enum/union types. It throws this JsonException when the deserializer hands it a JSON token that is not a string (e.g. a number, object, or array), because the target type can only be constructed from a string value.","triggerScenarios":"Deserializing JSON where a field mapped to a GeneratedStringEnumJson-backed type contains a non-string token, e.g. `\"role\": 1` instead of `\"role\": \"user\"`, or the JSON is `null`/an object where a string enum is expected.","commonSituations":"Hand-written JSON payloads, responses from a server whose schema changed to return numeric or object values, or JSON produced by a different serializer with different type conventions.","solutions":["Fix the JSON payload so the field is a string matching the enum value (e.g. \"user\" not 1).","Check the API/server for a version change that altered the field's type.","If the value can legitimately be absent, make the property nullable so the converter is not invoked for null tokens.","Catch JsonException during deserialization and log reader position to identify the offending field."],"exampleFix":"// before\nvar m = JsonSerializer.Deserialize<Message>(json); // json: {\"source\": 1}\n// after\nvar m = JsonSerializer.Deserialize<Message>(\"{\\\"source\\\": \\\"user\\\"}\");","handlingStrategy":"try-catch","validationCode":"// pre-validate JSON field type\nusing var doc = JsonDocument.Parse(json);\nif (doc.RootElement.GetProperty(\"source\").ValueKind != JsonValueKind.String)\n    throw new ArgumentException(\"source must be a JSON string\");","typeGuard":"static bool IsStringToken(ref Utf8JsonReader r) => r.TokenType == JsonTokenType.String;","tryCatchPattern":"try { var m = JsonSerializer.Deserialize<Message>(json); }\ncatch (JsonException ex) { log.LogError(ex, \"invalid enum token at offset {Offset}\", ex.BytesConsumed); }","preventionTips":["Always emit enum fields as JSON strings","Contract-test payloads against the SDK schema","Pin server/client schema versions together","Validate payloads with a JSON schema before deserializing"],"tags":["json","deserialization","dotnet"],"backgroundTag":"type-mismatch","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}