{"record":{"id":"8f3db07c0fce57d6","repo":"microsoft/aspire","slug":"expected-a-string-token-for-kubernetes-microtime-but-found","errorCode":null,"errorMessage":"Expected a string token for Kubernetes MicroTime but found {reader.TokenType}.","messagePattern":"Expected a string token for Kubernetes MicroTime but found (.+?)\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/Dcp/Model/KubernetesMicroTimeJsonConverter.cs","lineNumber":24,"sourceCode":"using System.Text.Json.Serialization;\n\nnamespace Aspire.Hosting.Dcp.Model;\n\ninternal sealed class KubernetesMicroTimeJsonConverter : JsonConverter<DateTime?>\n{\n    private const string UtcFormat = \"yyyy-MM-dd'T'HH:mm:ss.ffffff'Z'\";\n    private const string OffsetFormat = \"yyyy-MM-dd'T'HH:mm:ss.ffffffzzz\";\n\n    public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n    {\n        if (reader.TokenType is JsonTokenType.Null)\n        {\n            return null;\n        }\n\n        if (reader.TokenType is not JsonTokenType.String)\n        {\n            throw new JsonException($\"Expected a string token for Kubernetes MicroTime but found {reader.TokenType}.\");\n        }\n\n        var value = reader.GetString();\n        if (string.IsNullOrEmpty(value))\n        {\n            throw new JsonException(\"Expected a non-empty Kubernetes MicroTime value.\");\n        }\n\n        return value.EndsWith('Z')\n            ? DateTime.ParseExact(value, UtcFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)\n            : DateTimeOffset.ParseExact(value, OffsetFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal).UtcDateTime;\n    }\n\n    public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options)\n    {\n        if (value is null)\n        {\n            writer.WriteNullValue();","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Dcp/Model/KubernetesMicroTimeJsonConverter.cs#L6-L42","documentation":"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.","triggerScenarios":"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\".","commonSituations":"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.","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."],"exampleFix":"// before\n{ \"lastUpdate\": 1704067200000 }\n// after\n{ \"lastUpdate\": \"2024-01-01T00:00:00.000000Z\" }","handlingStrategy":"validation","validationCode":"using var doc = JsonDocument.Parse(json);\nif (doc.RootElement.TryGetProperty(\"lastUpdate\", out var t) && t.ValueKind != JsonValueKind.String)\n    throw new FormatException(\"lastUpdate must be an RFC3339 string, not \" + t.ValueKind);","typeGuard":"static bool IsMicroTimeString(JsonElement e) => e.ValueKind == JsonValueKind.String && !string.IsNullOrEmpty(e.GetString());","tryCatchPattern":"try { time = JsonSerializer.Deserialize<KubernetesMicroTime>(ref reader, options); }\ncatch (JsonException ex) when (ex.Message.Contains(\"MicroTime\")) { time = null; /* log and continue */ }","preventionTips":["Ensure producers emit RFC3339 strings for Kubernetes timestamp fields.","Keep DCP and dashboard versions aligned.","Add contract tests asserting timestamp wire format."],"tags":["json","deserialization","kubernetes","timestamps"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}