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:190 — tx.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 f64 → StorageError::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.
Severity: LOW (robustness edge)
Component:
crates/storage-sqliteSummary
serde_jsonserializes a non-finitef64(NaN/±Infinity) to the literalnullrather than erroring, but deserializingnullback intof64does error. Becausesave_message_draftperforms a mandatory post-write reload (which re-parses the just-written waveform JSON) beforecommit, a draft attachment whosewaveform_samplescontains any non-finite value writes successfully but fails to reload — and the?returns beforetx.commit(), rolling the entire save back. Such a draft can never be persisted, and the failure surfaces as an opaqueStorageError::Serializationrather 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 onnull).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:190—tx.commit().Concrete failure scenario
Call
save_message_draftwith an attachment whosewaveform_samplescontainsf64::NAN(or an infinity).insert_message_draft_attachmentwriteswaveform_samples_json = "[null]"successfully, but the mandatory reload fails deserializingnullintof64→StorageError::Serialization→ early return beforecommit→ 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.