v1.3.8-beta — object registration fix#36
Conversation
…imit The insert-pending-objects batch used max 5 rows per INSERT, but each objects row binds 21 parameters (20 explicit columns plus the auto-bound updated_at), so a five-row chunk sent 105 and D1 rejected it. Registering exactly five or more unregistered images failed after the images were already committed to the repository, leaving them out of objects.csv and the database. The batch now holds at most four rows (84 parameters). Adds a regression test asserting the 4+1 chunking.
There was a problem hiding this comment.
Pull request overview
Fixes an object-registration edge case where inserting 5+ new objects could exceed Cloudflare D1’s 100-bound-parameter limit, causing the DB insert to fail after images were already committed to the repo (repo/D1 divergence).
Changes:
- Adjusts the objects INSERT batching to cap chunks at 4 rows per statement (accounting for Drizzle’s
updated_atauto-bind). - Adds a regression test that asserts the 5-object boundary chunks as
4 + 1. - Bumps displayed/documented version references to
v1.3.8-betaand adds a changelog entry.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
app/routes/_app.objects.tsx |
Fixes INSERT chunk sizing for insert-pending-objects to stay within D1 bound-parameter limits. |
tests/insert-pending-objects-hardening.test.ts |
Adds a regression test validating chunking behavior at the 5-object boundary. |
CHANGELOG.md |
Documents the v1.3.8-beta fix release and impact/remediation steps. |
README.md |
Updates displayed beta version to 1.3.8-beta (EN/ES sections). |
app/components/layout/Footer.tsx |
Updates UI footer version string to 1.3.8-beta. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // objects appear in the shared doc only after the repo build succeeds | ||
| // and the D1 INSERT completes; the snapshot writes them as UPDATEs on | ||
| // the next cycle). | ||
| const maxRows = 4; |
There was a problem hiding this comment.
Keeping the explicit 4 here on purpose. The bug being fixed was itself a Math.floor(100 / 20) whose divisor was silently wrong — it missed the auto-bound updated_at, so a 5-row chunk bound 21 × 5 = 105 params and overflowed D1's 100-parameter limit. A floor(100 / N) form reads as principled and invites trusting the constant, which is how the wrong count survived several releases. A plain 4, with the comment spelling out the 21-params-per-row math, forces a reader to engage with the reasoning, and it leaves ~4 columns of headroom (safe until a row binds more than 25 params).
The genuine improvement — deriving the per-row count from the row shape so it can't drift when a column is added — is worth doing, but across all the chunked inserts: the chunkForD1 call sites in import.server.ts / sync.server.ts hard-code their column counts too, and the steps inserts already sit at 98/100. Better as a separate follow-up than folded into this fix.
Fixes a bug where registering five or more unregistered objects at once could fail after the images had already been committed to the repository, leaving them out of the objects list and
objects.csv. The batch insert into D1 now stays within the 100-bound-parameter limit (each objects row binds 21 parameters, so the batch is capped at four rows). Adds a regression test for the chunking boundary.See the CHANGELOG entry for v1.3.8-beta. No database migrations.