microsoft/aspire · error · JsonException
Expected a string token for Kubernetes MicroTime but found
Error message
Expected a string token for Kubernetes MicroTime but found {reader.TokenType}. What it means
Thrown by KubernetesMicroTimeJsonConverter.Read when deserializing a Kubernetes MicroTime JSON value that is not a JSON string. The converter expects the token to be JsonTokenType.String so it can parse RFC3339 timestamps; any other token (number, null handled earlier, object) raises a JsonException.
Solutions
- Fix the producing side to emit RFC3339 strings (e.g. "2024-01-01T12:00:00.123456Z") instead of numeric epochs.
- If you control deserialization, pre-parse with a JsonDocument check and convert numeric values to ISO strings before binding.
- Upgrade the component that produced the payload — older/mismatched DCP versions may emit incompatible timestamp formats.
Example fix
// before
{ "lastUpdate": 1704067200000 }
// after
{ "lastUpdate": "2024-01-01T00:00:00.000000Z" } Defensive patterns
Strategy: validation
Validate before calling
using var doc = JsonDocument.Parse(json);
if (doc.RootElement.TryGetProperty("lastUpdate", out var t) && t.ValueKind != JsonValueKind.String)
throw new FormatException("lastUpdate must be an RFC3339 string, not " + t.ValueKind); Type guard
static bool IsMicroTimeString(JsonElement e) => e.ValueKind == JsonValueKind.String && !string.IsNullOrEmpty(e.GetString());
Try / catch
try { time = JsonSerializer.Deserialize<KubernetesMicroTime>(ref reader, options); }
catch (JsonException ex) when (ex.Message.Contains("MicroTime")) { time = null; /* log and continue */ } Prevention
- Ensure producers emit RFC3339 strings for Kubernetes timestamp fields.
- Keep DCP and dashboard versions aligned.
- Add contract tests asserting timestamp wire format.
When it happens
Trigger: Deserializing a DCP/Kubernetes JSON payload where a field typed as MicroTime contains a numeric epoch value or an object instead of an RFC3339 string such as "2024-01-01T12:00:00Z".
Common situations: A non-Kubernetes-compliant server or mock returning epoch milliseconds for timestamp fields; hand-edited or corrupted DCP state files; version drift between dashboard and DCP emitting different timestamp shapes.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- Expected a non-empty Kubernetes MicroTime value.
- Cannot convert string
- Error deserializing GenAI message content. Error description
- Expected PropertyName, got
- Expected StartObject, got
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/8f3db07c0fce57d6.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/Dcp/Model/KubernetesMicroTimeJsonConverter.cs:24
using System.Text.Json.Serialization;
namespace Aspire.Hosting.Dcp.Model;
internal sealed class KubernetesMicroTimeJsonConverter : JsonConverter<DateTime?>
{
private const string UtcFormat = "yyyy-MM-dd'T'HH:mm:ss.ffffff'Z'";
private const string OffsetFormat = "yyyy-MM-dd'T'HH:mm:ss.ffffffzzz";
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType is JsonTokenType.Null)
{
return null;
}
if (reader.TokenType is not JsonTokenType.String)
{
throw new JsonException($"Expected a string token for Kubernetes MicroTime but found {reader.TokenType}.");
}
var value = reader.GetString();
if (string.IsNullOrEmpty(value))
{
throw new JsonException("Expected a non-empty Kubernetes MicroTime value.");
}
return value.EndsWith('Z')
? DateTime.ParseExact(value, UtcFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)
: DateTimeOffset.ParseExact(value, OffsetFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal).UtcDateTime;
}
public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options)
{
if (value is null)
{
writer.WriteNullValue();View on GitHub (pinned to 25830f84bd)