iOfficeAI/OfficeCLI · warning · JsonException
Unexpected token {reader.TokenType} for prop value '{key}'
Error message
Unexpected token {reader.TokenType} for prop value '{key}' What it means
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.
Source
Thrown at src/officecli/BatchTypes.cs:51
throw new JsonException("Unexpected end of JSON");
}
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException("Expected object or [\"key=value\"] array for props");
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject) return dict;
if (reader.TokenType != JsonTokenType.PropertyName)
throw new JsonException("Expected property name");
var key = reader.GetString()!;
reader.Read();
var value = reader.TokenType switch
{
JsonTokenType.String => reader.GetString()!,
JsonTokenType.Number => reader.TryGetInt64(out var l) ? l.ToString() : reader.GetDouble().ToString(),
JsonTokenType.True => "true",
JsonTokenType.False => "false",
JsonTokenType.Null => "",
_ => throw new JsonException($"Unexpected token {reader.TokenType} for prop value '{key}'")
};
dict[key] = value;
}
throw new JsonException("Unexpected end of JSON");
}
public override void Write(Utf8JsonWriter writer, Dictionary<string, string> value, JsonSerializerOptions options)
{
writer.WriteStartObject();
foreach (var kv in value)
writer.WriteString(kv.Key, kv.Value);
writer.WriteEndObject();
}
}
internal class BatchItemConverter : JsonConverter<BatchItem>
{
private static readonly LenientStringDictionaryConverter PropsConverter = new();View on GitHub (pinned to 1ced45e900)
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.
Example fix
// before: { command:'set', props: { style: { bold: true, size: 14 } } }
// after: { command:'set', props: { bold: 'true', size: '14' } } // flat string map Defensive patterns
Strategy: type-guard
Validate before calling
// Flatten props to a string map before serializing
function flattenProps(p) {
const out = {};
for (const [k, v] of Object.entries(p || {})) out[k] = (typeof v === 'object') ? JSON.stringify(v) : String(v);
return out;
} Type guard
// props values must be scalar (string|number|boolean), not nested objects/arrays
function isFlatProps(p) {
if (p == null) return true;
return Object.values(p).every(v => v == null || ['string','number','boolean'].includes(typeof v));
} Prevention
- 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.
When it happens
Trigger: "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.
Common situations: An agent that wants to set a rich/structured cell style but passes a nested object; reusing a config object verbatim as props.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Expected "key=value" string in props array
- Expected object or ["key=value"] array for props
- Unexpected end of JSON
- Expected property name
- Expected StartObject for BatchItem
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/8ae75cf7abcdbfed.
Report an issue: GitHub.