2.6 KiB
id, title, status, assignee, created_date, labels, dependencies, references, modified_files, priority
| id | title | status | assignee | created_date | labels | dependencies | references | modified_files | priority | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ML-171 | Fix Oban Web crons page crash: MatchError in sparkline from SQLite datetime string | To Do | 2026-05-09 05:28 |
|
|
|
medium |
Description
Summary
The /dev/oban/crons dashboard page crashes with Elixir.MatchError when rendering cron job history sparklines. This happens because Oban Web's TableComponent.sparkline/1 calls DateTime.from_naive!/2 which expects a NaiveDateTime struct, but receives a raw ISO 8601 string from SQLite.
Root Cause
In Oban.Web.CronQuery.cron_history/2 (deps/oban_web/lib/oban/web/queries/cron_query.ex:164-177), the query selects:
finished_at: fragment("COALESCE(?, ?, ?)", j.completed_at, j.cancelled_at, j.discarded_at)
SQLite stores utc_datetime_usec fields as ISO 8601 text. While regular field references like j.scheduled_at are properly decoded to DateTime structs by Ecto, the fragment() call bypasses type decoding and returns a raw string like "2026-05-08T11:00:00.708342Z".
The sparkline function at Oban.Web.Crons.TableComponent line 81 then fails:
(job.finished_at || job.attempted_at || job.scheduled_at)
|> DateTime.from_naive!("Etc/UTC") # 💥 expects NaiveDateTime, gets string
Error Details
- ErrorTracker ID: 4039
- Occurrences: 2 (both on 2026-05-08)
- View: Oban.Web.DashboardLive (crons page)
- Fingerprint:
2C5253F1AB9B5D61231B7579E912FD2F7C155738DBB4325275F14E844C5D7B0C
Approach
The sparkline/1 function is marked as @doc overridable: 1 in Oban Web, so we can override it in the app. The fix should handle both DateTime structs (PostgreSQL) and ISO 8601 strings (SQLite) by parsing strings through DateTime.from_iso8601!/1 first.
Alternatively, the fix could be applied upstream in Oban Web's CronQuery to use a typed fragment or cast the COALESCE result.
Acceptance Criteria
- #1 Visiting /dev/oban/crons no longer crashes with MatchError
- #2 Cron history sparklines render correctly showing job state colors
- #3 The fix handles both DateTime structs (PostgreSQL) and ISO 8601 strings (SQLite)
- #4 The overridden sparkline/1 function preserves the same visual output as upstream