Skip to content

Scaffold multipart uploads: best-effort delete newly-saved blobs on validation/DB failure #1872

Description

@madmax983

Problem

The generated create/update handlers stream the uploaded file to the blob store during multipart parsing (autumn-cli/src/generate/scaffold.rs ~2089, field.save_to_blob_store(...)) — i.e. before changeset validation (~2355 create / ~2445 update) and before the DB write. So every early return leaves the just-saved blob orphaned in the store:

  • 422 invalid changeset,
  • unique-violation 422 (~2322 create / ~2382 update),
  • generic DB Err (~2329 create / ~2389 update).

The blob is leaked on ordinary invalid submissions, not just on rare error paths.

Available primitives

  • BlobStore::delete (autumn/src/storage/mod.rs:279) is a no-op if the key is absent, and is available on the store the handler already holds.
  • Blob.key is public.

Framework context (informs the fix)

The direct-upload path deliberately tolerates orphans: it relies on bind-step promotion and delegates cleanup to a periodic sweep / lifecycle policy (autumn/src/storage/direct_upload.rs:16-32). So the fix here should be a deliberate, consistent design choice rather than an ad-hoc patch, choosing between:

  1. Eager best-effort delete on all early-return paths — careful to distinguish a newly-saved blob from a preserved existing blob on update (update's .or(current.image) must not delete the preserved one), or
  2. A documented sweep matching the direct-upload path's model.

Scope

Cover all early returns (422 validation, unique-violation 422, generic DB error) on both create and update — not just the 422 path.

Found during review of #1867 (Part of #1236). Sibling to the CSRF follow-up #1866.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions