The schema-less API cannot read a typed collection that holds a document larger than one page: FindAllAsync and BLiteMigration throw "Skipping type 69"
Maintainers usually reply within 2 days
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
Research direction
Start with src/BLite.Core/DynamicCollection.cs, especially ValidateWrite and the scan/lookup paths, and compare overflow handling with src/BLite.Core/Collections/DocumentCollection.cs; also inspect src/BLite.Bson/BsonSpanReader.cs. Review src/BLite.Core/BLiteMigration.cs to understand how the schema-less read and write paths affect migrations, including cleanup on failure. Use the store-model tests described in the issue for documents larger than a page and add a migration round-trip test; success means large typed documents are readable and migratable, or the documented limitation and preflight failure behavior are implemented.
Written by the indexing model from the issue text.
Description
A typed collection stores a document larger than one page (about 16 KB with the default 16 KB pages) in overflow pages. The schema-less API cannot read such a collection: DynamicCollection.FindAllAsync throws NotSupportedException: Skipping type 69 not supported at position 7 when it reaches the document. Everything built on that API fails the same way, including BLiteMigration.ToMultiFileAsync / ToSingleFileAsync, so a database with one large typed document cannot be migrated between layouts. DynamicCollection also refuses to write such a document ("Document size … exceeds maximum single page size. Overflow not yet supported in DynamicCollection."), which neither the README nor the docs mention.
Found while checking the secure-erase behaviour for #299.
Repro
public class Person { public ObjectId Id { get; set; } public string Name { get; set; } = ""; }
public partial class OvfDbContext : DocumentDbContext
{
public DocumentCollection<ObjectId, Person> People { get; set; } = null!;
public OvfDbContext(string path) : base(path) { }
}
await using (var db = new OvfDbContext("app.db"))
{
await db.People.InsertAsync(new Person { Name = "small" });
await db.People.InsertAsync(new Person { Name = new string('x', 40_000) }); // overflow pages
await db.SaveChangesAsync();
}
// 1. The same file through the schema-less API
using (var engine = new BLiteEngine("app.db"))
await foreach (var d in engine.GetOrCreateCollection("persons").FindAllAsync()) { }
// NotSupportedException: Skipping type 69 not supported at position 7
// 2. Layout migration
await BLiteMigration.ToMultiFileAsync("app.db", PageFileConfig.Server("app.db"));
// NotSupportedException: Skipping type 69 not supported at position 7
After the failed migration the source is intact: the typed context still reads both documents, including the 40,000-character name. The migration does leave the empty multi-file layout next to the source (app.idx, 1 MB; wal/app.wal; collections/app/).
Expected: the schema-less API reads every document the typed API wrote, and BLiteMigration copies them; or, if DynamicCollection deliberately has no overflow support, the limit is documented and the migration says which document it cannot copy before it starts.
Actual: an exception from the BSON reader with a byte position and a type code, at the first large document.
Where in the code (0450b97)
DynamicCollectionhas no overflow handling on the read path. A slot flaggedSlotFlags.HasOverflowholds a 4-byte length and a 4-byte next-page id before the document bytes (written byDocumentCollectionatsrc/BLite.Core/Collections/DocumentCollection.cs:2204-2205;DynamicCollection.csnever checksHasOverflow).DynamicCollectionhands the slot bytes toBsonSpanReaderas if they were a document, so the reader meets a byte that is not a BSON type (src/BLite.Bson/BsonSpanReader.cs:484).- Writes are refused by size:
ValidateWrite(src/BLite.Core/DynamicCollection.cs:2233-2235), with_maxDocumentSizeForSinglePage = PageSize - 128(DynamicCollection.cs:120); TimeSeries collections are exempt from the check. BLiteMigrationcopies every collection through the schema-less API:source.GetOrCreateCollection(collName)andtargetColl.InsertBulkAsync(batch)(src/BLite.Core/BLiteMigration.cs:225-261), so it fails on the read side first and would fail on the write side next.- BLite Studio opens a collection with
engine.GetOrCreateCollection(name)(tools/BLite.Studio/ViewModels/Explorer/CollectionDetailViewModel.cs:28), and BLQL runs onDynamicCollection, so both are affected the same way (inferred from the code, not run).
Fix considerations
- Read side first: follow the overflow chain in
DynamicCollection's scan and lookup paths, asDocumentCollectiondoes. That alone makes Studio, BLQL and the source side ofBLiteMigrationwork on these databases. - Write side: overflow on insert and update in
DynamicCollection, or a documented limit. The migration needs one of the two, since its target is also aDynamicCollection. The LiteDB import of #297 writes toDynamicCollectiontoo, and LiteDB documents can be much larger than a page. BLiteMigration: clean up the target's sub-files on failure, not only the.migratingtemp file.- Tests: the store model of #250 with document sizes past one page, read back through both APIs; a migration round trip with a large document.
Related: #297 (LiteDB import writes to DynamicCollection), #296 (stability matrix: what the schema-less API supports), #299 (found while checking it).
- Dominant language
- C#
- Stars
- 66
- Forks
- 6
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 58
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from EntglDb/BLite
-
GdprMode.Strict warns that deleted documents are not zeroed, but every delete zero-fills themPossibly taken @CaffeinatedCoder claimed this 1 day ago. Openbug gdpr package/core severity/low
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
EntglDb/BLite#299 · 1 comment ·
Maintainers usually reply within 2 days
-
bug package/core severity/medium triage
Difficulty 4/5 3-5 days Newbie friendliness 54/100
Maintainers usually reply within 2 days
-
bug package/core severity/medium
Difficulty 4/5 3-5 days Newbie friendliness 48/100
EntglDb/BLite#322 · 1 comment ·
Maintainers usually reply within 2 days
-
enhancement package/core
Difficulty 4/5 3-5 days Newbie friendliness 48/100
EntglDb/BLite#320 · 1 comment ·
Maintainers usually reply within 2 days
-
BLiteSession.Rollback() does not await the rollback: it returns while the transaction is still active, and failures go unobservedPossibly taken @CaffeinatedCoder claimed this 1 day ago. Openbug package/core severity/medium
Difficulty 3/5 1-2 days Newbie friendliness 78/100
EntglDb/BLite#307 · 1 comment ·
Maintainers usually reply within 2 days
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
swisstopo/swissgeol-boreholes-suite#3086 ·
Maintainers usually reply within 1 day
-
byte类型在条件中的解析BUGOpen
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
dotnetcore/FreeSql#2290 ·
-
status:waiting-for-triage type:bug
Difficulty 1/5 Under an hour Newbie friendliness 84/100
microsoftgraph/msgraph-sdk-dotnet#3194 ·
Maintainers usually reply within 1 day
-
Backend enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
Maintainers usually reply within 1 day
-
UI: money shows the minus sign next to the number, not before the currency (IL -3.0m, not -IL 3.0m)Openarea: sim area: unity enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
eyalgolan/statecraft-israel#1107 · 1 comment ·
Maintainers usually reply within 1 day