GET /api/activity/adoption (GetPlatformAdoptionQuery → CollectSubmittedCodeAsync) throws in production:
System.FormatException: Cannot deserialize a 'String' from BsonType 'Array'.
at MongoDB.EntityFrameworkCore.Serializers.ValueConverterSerializer`2.Deserialize(...)
at MongoDB.EntityFrameworkCore.Query.QueryingEnumerable`2.Enumerator.MoveNextAsync()
(Version 2.1.5, Production-Main)
Root cause
Serialization contract mismatch on UserSubmittedCode.TestResults (List<TestResult>):
Write path — SpikerSoft.EventHandlers.CodeExecution.Services.UserSubmittedCodeService uses the raw MongoDB driver (IMongoCollection<UserSubmittedCode>), which stores TestResults as a native embedded BSON array of subdocuments. This is how every graded submission is written.
Read path — SpikerDbContext.ConfigureUserSubmittedCodeEntity had a HasConversion that serialized/deserialized TestResults as a JSON string. When EF materializes a driver-written row it tries to read the array element as a String and throws.
Nothing in the codebase ever wrote a JSON string, so the converter was dead-on-arrival and crashed on all real data.
Blast radius
Two EF read sites materialize UserSubmittedCode and hit this:
GetPlatformAdoptionQueryHandler.CollectSubmittedCodeAsync (the reported endpoint).
Remove the JSON-string HasConversion and map TestResults as an owned embedded collection (entity.OwnsMany(e => e.TestResults)) so EF reads the same native array shape the driver writes. Regression covered by an integration test that writes via the driver and reads back through EF.
## Summary
`GET /api/activity/adoption` (`GetPlatformAdoptionQuery` → `CollectSubmittedCodeAsync`) throws in production:
```
System.FormatException: Cannot deserialize a 'String' from BsonType 'Array'.
at MongoDB.EntityFrameworkCore.Serializers.ValueConverterSerializer`2.Deserialize(...)
at MongoDB.EntityFrameworkCore.Query.QueryingEnumerable`2.Enumerator.MoveNextAsync()
```
(Version 2.1.5, Production-Main)
## Root cause
Serialization contract mismatch on `UserSubmittedCode.TestResults` (`List<TestResult>`):
- **Write path** — `SpikerSoft.EventHandlers.CodeExecution.Services.UserSubmittedCodeService` uses the raw MongoDB driver (`IMongoCollection<UserSubmittedCode>`), which stores `TestResults` as a **native embedded BSON array** of subdocuments. This is how *every* graded submission is written.
- **Read path** — `SpikerDbContext.ConfigureUserSubmittedCodeEntity` had a `HasConversion` that serialized/deserialized `TestResults` as a **JSON string**. When EF materializes a driver-written row it tries to read the array element as a `String` and throws.
Nothing in the codebase ever wrote a JSON string, so the converter was dead-on-arrival and crashed on all real data.
## Blast radius
Two EF read sites materialize `UserSubmittedCode` and hit this:
1. `GetPlatformAdoptionQueryHandler.CollectSubmittedCodeAsync` (the reported endpoint).
2. `ProcessSonarQubeWebhookCommandHandler` (`FirstOrDefaultAsync(x => x.GitCommit == ...)`).
## Fix
Remove the JSON-string `HasConversion` and map `TestResults` as an owned embedded collection (`entity.OwnsMany(e => e.TestResults)`) so EF reads the same native array shape the driver writes. Regression covered by an integration test that writes via the driver and reads back through EF.
Resolved in spikersoft-backend PR #199 (merged): UserSubmittedCode.TestResults read as native BSON array instead of a JSON string — GET /api/activity/adoption no longer throws FormatException. Closing.
Resolved in spikersoft-backend PR #199 (merged): UserSubmittedCode.TestResults read as native BSON array instead of a JSON string — GET /api/activity/adoption no longer throws FormatException. Closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
GET /api/activity/adoption(GetPlatformAdoptionQuery→CollectSubmittedCodeAsync) throws in production:(Version 2.1.5, Production-Main)
Root cause
Serialization contract mismatch on
UserSubmittedCode.TestResults(List<TestResult>):SpikerSoft.EventHandlers.CodeExecution.Services.UserSubmittedCodeServiceuses the raw MongoDB driver (IMongoCollection<UserSubmittedCode>), which storesTestResultsas a native embedded BSON array of subdocuments. This is how every graded submission is written.SpikerDbContext.ConfigureUserSubmittedCodeEntityhad aHasConversionthat serialized/deserializedTestResultsas a JSON string. When EF materializes a driver-written row it tries to read the array element as aStringand throws.Nothing in the codebase ever wrote a JSON string, so the converter was dead-on-arrival and crashed on all real data.
Blast radius
Two EF read sites materialize
UserSubmittedCodeand hit this:GetPlatformAdoptionQueryHandler.CollectSubmittedCodeAsync(the reported endpoint).ProcessSonarQubeWebhookCommandHandler(FirstOrDefaultAsync(x => x.GitCommit == ...)).Fix
Remove the JSON-string
HasConversionand mapTestResultsas an owned embedded collection (entity.OwnsMany(e => e.TestResults)) so EF reads the same native array shape the driver writes. Regression covered by an integration test that writes via the driver and reads back through EF.Resolved in spikersoft-backend PR #199 (merged): UserSubmittedCode.TestResults read as native BSON array instead of a JSON string — GET /api/activity/adoption no longer throws FormatException. Closing.