Skip to content

fix(workspaces): make upload name resolution and insert atomic#618

Draft
posthog[bot] wants to merge 1 commit into
mainfrom
posthog-code/fix-concurrent-upload-name-collision
Draft

fix(workspaces): make upload name resolution and insert atomic#618
posthog[bot] wants to merge 1 commit into
mainfrom
posthog-code/fix-concurrent-upload-name-collision

Conversation

@posthog

@posthog posthog Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

What changed

WorkspaceKernelFileCommands.createFileFromUpload now resolves the collision-free item name and runs the INSERT INTO kernel_items in the same synchronous event-loop turn. The awaited writeFileBytes / r2.delete calls were moved to before name resolution, so nothing suspends between resolveItemName and the insert.

Why

Concurrent uploads of the same filename to the same parent could fail with a SQLite UNIQUE constraint failed: kernel_items.name error. The workspace kernel is a Cloudflare Durable Object, so concurrent RPC calls interleave at await points. With the awaited file/R2 work sitting between name resolution and the insert, two simultaneous uploads could both resolve to the same name (neither row inserted yet), and the second insert then collided on the partial unique index — a classic check-then-act (TOCTOU) race. The user observed a 500 UPLOAD_FAILED; the auto-rename logic is correct serially, which is why a retry succeeds.

Reordering is safe because shellPath and the metadata are derived from itemId / requestedName, not the resolved name.

Testing notes

  • Verified via code inspection that no await remains between resolveItemName and the INSERT (getNextSortOrder is synchronous), closing the interleaving window in the single-threaded DO.
  • Typecheck of the changed file surfaced no new errors (pre-existing vite/client / node type-lib config errors are unrelated to this change).

Created with PostHog Code from an inbox report.


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.

Review in cubic

Concurrent uploads of the same filename to the same parent could fail with a
SQLite UNIQUE constraint error on kernel_items.name. The workspace kernel is a
Durable Object, so concurrent RPC calls interleave at `await` points. Because
`resolveItemName` and the `INSERT` were separated by the awaited
`writeFileBytes` / `r2.delete` calls, two simultaneous uploads could both
resolve to the same collision-free name (neither inserted yet), then the second
insert collided on the partial unique index — a check-then-act (TOCTOU) race.

Move the awaited file/R2 work before name resolution so `resolveItemName` and
the synchronous `INSERT` run in the same event-loop turn with no suspension
between them. `shellPath` and metadata are derived from `itemId`/`requestedName`,
not the resolved `name`, so reordering is safe.

Generated-By: PostHog Code
Task-Id: 888b423f-9eae-481d-b17d-49619571f76f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

0 participants