{"record":{"id":"060e270852fc637c","repo":"elsa-workflows/elsa-core","slug":"the-persisted-external-authentication-value-could-not-be","errorCode":null,"errorMessage":"The persisted external authentication value could not be deserialized as {typeof(T).Name}.","messagePattern":"The persisted external authentication value could not be deserialized as (.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.ExternalAuthentication.Persistence.EFCore/ExternalAuthenticationJsonSerializer.cs","lineNumber":12,"sourceCode":"using System.Text.Json;\n\nnamespace Elsa.ExternalAuthentication.Persistence.EFCore;\n\ninternal static class ExternalAuthenticationJsonSerializer\n{\n    private static readonly JsonSerializerOptions Options = new(JsonSerializerDefaults.Web);\n\n    public static string Serialize<T>(T value) => JsonSerializer.Serialize(value, Options);\n\n    public static T Deserialize<T>(string value) => JsonSerializer.Deserialize<T>(value, Options)\n        ?? throw new InvalidOperationException($\"The persisted external authentication value could not be deserialized as {typeof(T).Name}.\");\n}\n","sourceCodeStart":1,"sourceCodeEnd":14,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.ExternalAuthentication.Persistence.EFCore/ExternalAuthenticationJsonSerializer.cs#L1-L14","documentation":"Thrown by ExternalAuthenticationJsonSerializer.Deserialize<T> when the persisted string cannot be deserialized into T as a non-null value. The helper uses JsonSerializerDefaults.Web and treats a null result (JSON 'null' literal or shape mismatch producing null) as a hard failure, since a persisted external-authentication payload must always be a valid value of T.","triggerScenarios":"Calling Deserialize<T> on a column value that is the JSON literal 'null', or whose JSON shape does not match T (e.g. stored JSON for a different type, empty object where a record with required properties is expected, or a value written by an older/different schema).","commonSituations":"EF Core external-authentication tables edited or truncated by hand; rows written by an older Elsa version before a payload-type change; copy/paste errors seeding the database; migrations that altered the payload shape without re-serializing existing rows.","solutions":["Inspect the persisted string and re-serialize it to the expected type T (matching the Web defaults: camelCase, case-insensitive) before use, e.g. Serialize<T>(correctValue).","If the row is stale from a schema change, migrate or delete the row and let the provisioning flow recreate it.","Confirm T matches the type originally stored; deserialize to the legacy type first and map to the new type if a version change occurred.","Guard callers: validate the raw value parses (JsonNode.Parse) and its shape matches T before invoking Deserialize."],"exampleFix":"// before\nvar state = ExternalAuthenticationJsonSerializer.Deserialize<LinkState>(raw); // raw is 'null'\n// after\nvar state = string.IsNullOrWhiteSpace(raw)\n    ? null\n    : ExternalAuthenticationJsonSerializer.Deserialize<LinkState>(raw);\nif (state is null) { /* recreate the link */ }","handlingStrategy":"validation","validationCode":"bool canDeserialize = !string.IsNullOrWhiteSpace(raw)\n    && JsonNode.Parse(raw) is not null\n    && JsonSerializer.Deserialize<T>(raw, new JsonSerializerOptions(JsonSerializerDefaults.Web)) is not null;","typeGuard":"static bool IsDeserializableAs<T>(string? raw) where T : class\n{\n    if (string.IsNullOrWhiteSpace(raw)) return false;\n    try { return JsonSerializer.Deserialize<T>(raw, new JsonSerializerOptions(JsonSerializerDefaults.Web)) is not null; }\n    catch (JsonException) { return false; }\n}","tryCatchPattern":"try { value = ExternalAuthenticationJsonSerializer.Deserialize<T>(raw); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"could not be deserialized\"))\n{\n    logger.LogWarning(ex, \"Persisted payload corrupt; recreating\");\n    value = null; // fall back to recreating the persisted state\n}","preventionTips":["Always write persisted values through Serialize<T> so shapes stay consistent","Round-trip Serialize/Deserialize in tests when changing payload types","Migrate old rows before switching to a new payload type","Reject NULL/garbage at the data-access layer before deserialization"],"tags":["json","serialization","ef-core","persistence"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}