{"record":{"id":"8ae75cf7abcdbfed","repo":"iOfficeAI/OfficeCLI","slug":"unexpected-token-reader-tokentype-for-prop-value","errorCode":null,"errorMessage":"Unexpected token {reader.TokenType} for prop value '{key}'","messagePattern":"Unexpected token (.+?) for prop value '(.+?)'","errorType":"validation","errorClass":"JsonException","httpStatus":null,"severity":"warning","filePath":"src/officecli/BatchTypes.cs","lineNumber":51,"sourceCode":"            throw new JsonException(\"Unexpected end of JSON\");\n        }\n        if (reader.TokenType != JsonTokenType.StartObject)\n            throw new JsonException(\"Expected object or [\\\"key=value\\\"] array for props\");\n        while (reader.Read())\n        {\n            if (reader.TokenType == JsonTokenType.EndObject) return dict;\n            if (reader.TokenType != JsonTokenType.PropertyName)\n                throw new JsonException(\"Expected property name\");\n            var key = reader.GetString()!;\n            reader.Read();\n            var value = reader.TokenType switch\n            {\n                JsonTokenType.String => reader.GetString()!,\n                JsonTokenType.Number => reader.TryGetInt64(out var l) ? l.ToString() : reader.GetDouble().ToString(),\n                JsonTokenType.True => \"true\",\n                JsonTokenType.False => \"false\",\n                JsonTokenType.Null => \"\",\n                _ => throw new JsonException($\"Unexpected token {reader.TokenType} for prop value '{key}'\")\n            };\n            dict[key] = value;\n        }\n        throw new JsonException(\"Unexpected end of JSON\");\n    }\n\n    public override void Write(Utf8JsonWriter writer, Dictionary<string, string> value, JsonSerializerOptions options)\n    {\n        writer.WriteStartObject();\n        foreach (var kv in value)\n            writer.WriteString(kv.Key, kv.Value);\n        writer.WriteEndObject();\n    }\n}\n\ninternal class BatchItemConverter : JsonConverter<BatchItem>\n{\n    private static readonly LenientStringDictionaryConverter PropsConverter = new();","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/BatchTypes.cs#L33-L69","documentation":"JsonException from LenientStringDictionaryConverter.Read inside the OBJECT branch: the value for a props key is a token type the converter won't coerce — specifically a nested object or array (StartObject/StartArray), since strings/numbers/booleans/null are all accepted and stringified. The message names the offending key and token type.","triggerScenarios":"\"props\": { \"style\": {\"bold\":true} } (a nested object), or \"props\": { \"vals\": [1,2,3] } (a nested array). officecli props are flat string maps; nested structures are not supported.","commonSituations":"An agent that wants to set a rich/structured cell style but passes a nested object; reusing a config object verbatim as props.","solutions":["Flatten the value to a string, e.g. props: { style: 'bold' } or a serialized form the command accepts.","Use the command-specific arguments officecli supports rather than nesting under props.","Confirm against the command's schema which props are scalar string-valued."],"exampleFix":"// before: { command:'set', props: { style: { bold: true, size: 14 } } }\n// after:  { command:'set', props: { bold: 'true', size: '14' } }  // flat string map","handlingStrategy":"type-guard","validationCode":"// Flatten props to a string map before serializing\nfunction flattenProps(p) {\n  const out = {};\n  for (const [k, v] of Object.entries(p || {})) out[k] = (typeof v === 'object') ? JSON.stringify(v) : String(v);\n  return out;\n}","typeGuard":"// props values must be scalar (string|number|boolean), not nested objects/arrays\nfunction isFlatProps(p) {\n  if (p == null) return true;\n  return Object.values(p).every(v => v == null || ['string','number','boolean'].includes(typeof v));\n}","tryCatchPattern":null,"preventionTips":["Keep props a flat string map; never nest objects/arrays as values.","Stringify any rich value before placing it in props.","Validate with isFlatProps() during development."],"tags":["batch","json","props","nested-value","deserialization","api-contract"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}