elsa-workflows/elsa-core · critical · DocumentStoreValidationException
Stored secret document
Error message
Stored secret document '{document.Id}' could not be deserialized. What it means
When loading a stored secret document, the repository JSON-deserializes the stored Content into a Secret using its configured serializer options. If the JSON is null/corrupt or does not deserialize to a Secret, it throws DocumentStoreValidationException. This protects callers from silently receiving a null Secret from damaged storage data.
Solutions
- Inspect the stored document Content in the database and fix or remove the corrupt row.
- Re-create the affected secret (delete the bad document, then add the secret again).
- Check for a version mismatch: data written by an older/newer Elsa version may need migration.
- Restore the document from a backup if the value cannot be reconstructed.
Defensive patterns
Strategy: try-catch
Validate before calling
// If you own the stored content, pre-check it:
try { using var _ = JsonDocument.Parse(content); } catch (JsonException) { throw new InvalidOperationException("Stored secret JSON is invalid."); } Type guard
bool IsValidStoredSecretJson(string content) { try { return JsonSerializer.Deserialize<JsonElement>(content).ValueKind == JsonValueKind.Object; } catch (JsonException) { return false; } } Try / catch
try { var secret = await secretRepository.GetAsync(id, ct); }
catch (DocumentStoreValidationException ex) { logger.LogError(ex, "Corrupt secret document {Id}", id); /* skip, repair, or fail fast */ } Prevention
- Do not edit secret documents in the database directly.
- Back up data before upgrading Elsa versions.
- Validate stored JSON after manual migrations or restores.
When it happens
Trigger: Calling GetAsync (or any read path via LoadDocumentAsync) on a stored document whose Content was written by an incompatible serializer version, manually edited, truncated, or whose schema no longer matches the current Secret type.
Common situations: Upgrading Elsa between versions where the stored Secret JSON schema changed; DB rows edited by hand or by external tooling; a migration or backup/restore that corrupted document content.
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
- Cannot convert to bool
- Cannot convert to bool?
- Cannot deserialize to .
- Expected a metadata property name.
- Expected a string metadata value.
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/1c962036b4bc03cd.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Secrets.Persistence.VNext/Repositories/VNextSecretRepository.cs:133
StorageUnitName,
NormalizeDocumentId(secret.Name),
JsonSerializer.Serialize(secret, _jsonOptions),
CreateIndexValues(secret),
expectedVersion);
await documentStore.SaveAsync(request, cancellationToken);
}
private async Task<(StoredDocument Document, Secret Secret)?> LoadDocumentAsync(string name, CancellationToken cancellationToken)
{
var document = await documentStore.LoadAsync(StorageUnitName, NormalizeDocumentId(name), cancellationToken);
return document is null ? null : (document, Deserialize(document));
}
private Secret Deserialize(StoredDocument document)
{
return JsonSerializer.Deserialize<Secret>(document.Content, _jsonOptions)
?? throw new DocumentStoreValidationException($"Stored secret document '{document.Id}' could not be deserialized.");
}
private static Dictionary<string, string?> CreateIndexValues(Secret secret)
{
return new()
{
[nameof(Secret.Name)] = secret.Name,
[nameof(Secret.TypeName)] = secret.TypeName,
[nameof(Secret.StoreName)] = secret.StoreName,
[nameof(Secret.Scope)] = secret.Scope,
[nameof(Secret.Status)] = secret.Status.ToString()
};
}
private static string NormalizeDocumentId(string name)
{
return name.Trim().ToLowerInvariant();
}View on GitHub (pinned to fe9217bdfa)