Skip to content

storage-sqlite: a non-finite f64 waveform sample makes a message draft permanently un-saveable (serde encode/decode asymmetry rolls back the whole save) #900

Description

@erskingardner

Severity: LOW (robustness edge)
Component: crates/storage-sqlite

Summary

serde_json serializes a non-finite f64 (NaN / ±Infinity) to the literal null rather than erroring, but deserializing null back into f64 does error. Because save_message_draft performs a mandatory post-write reload (which re-parses the just-written waveform JSON) before commit, a draft attachment whose waveform_samples contains any non-finite value writes successfully but fails to reload — and the ? returns before tx.commit(), rolling the entire save back. Such a draft can never be persisted, and the failure surfaces as an opaque StorageError::Serialization rather than a validation error.

Location

  • crates/storage-sqlite/src/message_drafts.rs:412-416 — encode: serde_json::to_string(&attachment.waveform_samples) (writes [null] for a non-finite sample, no error).
  • crates/storage-sqlite/src/message_drafts.rs:449-451 — decode: serde_json::from_str::<Vec<f64>>(&samples) (errors on null).
  • crates/storage-sqlite/src/message_drafts.rs:187 — the post-write reload (load_message_draft), which re-parses attachments; its ? returns before…
  • crates/storage-sqlite/src/message_drafts.rs:190tx.commit().

Concrete failure scenario

Call save_message_draft with an attachment whose waveform_samples contains f64::NAN (or an infinity). insert_message_draft_attachment writes waveform_samples_json = "[null]" successfully, but the mandatory reload fails deserializing null into f64StorageError::Serialization → early return before commit → the whole draft (text + all attachments) is rolled back and never saved.

Impact

A draft carrying a non-finite waveform amplitude is silently un-saveable, with a misleading error. Low reachability (audio waveform amplitudes are normally finite 0..1), so this is a robustness/validation edge rather than corruption.

Suggested fix

Reject or sanitize non-finite samples at the API boundary with a clear validation error (or encode them losslessly, e.g. filter/clamp to finite), so the encode/decode round-trip is total.

Dedup

No existing issue covers waveform-sample serialization. Unrelated to the checked-integer-conversion issues (#821/#871).


Filed from a meticulous automated code-review pass; verified against source and deduplicated against the existing open/closed issue set.

Metadata

Metadata

Assignees

No one assigned

    Labels

    LOWbugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions