Monitor refreshes
Read the Schedules page, the attention band, and the run history, so you can tell at a glance which dashboards are current and which are not.
Everything that refreshes on a schedule is on one page: dashies.xyz/app/schedules. This is how to read it.
A dashboard only appears there once it has a connected data source. A static dashboard has nothing to re-run, so it is absent rather than listed as idle.
The four things on the page
Top to bottom:
| Surface | Answers |
|---|---|
| The attention band | "Is anything broken right now?" |
| The scheduler caption | "Is the refresh engine even running?" |
| The tabs and table | "What is each dashboard doing?" |
| The History tab | "What actually happened, run by run?" |
The attention band
The band sits above everything else and lists only the dashboards that are Failing or Stale. It shows at most three, then a count of the rest.
Everything else is deliberately absent. A paused or archived dashboard is doing what it was told to, so listing it as needing attention would turn an exception feed into a second copy of the table.
When nothing is wrong the band collapses to one line:
All 12 dashboards are refreshing on schedule. Next refresh in 24m.
Each listed dashboard gets its name, its slug, a state line, and a Run now button. The state line separates a first miss from a stuck job, because those need different reactions:
The last refresh failed. Last updated 2h ago.
6 refreshes in a row have failed. Last updated 2w ago.
Last updated 3d ago, which is past its refresh interval.
A dashboard that has never completed a run reads Has never refreshed in place
of the Last updated clause.
The band does not name the reason yet
It tells you which dashboards are broken and how long they have been broken, not why. For the classified reason and the remedy, open History and select the dashboard.
A lapsed plan is reported separately. When that is the only thing wrong, the band is replaced entirely by a banner counting the paused dashboards, with a link to resume them.
The table's default sort is Problems first, which orders it by the same urgency the band uses, so the band's dashboards are also the table's top rows. Switching the sort to Next run, Last run, or Name breaks that alignment on purpose, and the band stops claiming the rows are listed below.
The scheduler caption
Under the band, one line reports whether the refresh engine itself is alive:
Scheduler active - last swept 3m ago
Past 20 minutes it turns amber and reads Scheduler may be delayed. The line is
hidden entirely when the heartbeat cannot be read.
This distinguishes the two failures that look identical from a dashboard row: the scheduler is running and your dashboard is broken, or the scheduler is not running and every dashboard is frozen. If the caption is amber, nothing is wrong with the dashboards.
The Data column
Every row carries exactly one verdict. It answers "can I trust these numbers", not "does a schedule exist", so there is no green "Active" that stays true while something else is wrong. The most severe applicable verdict wins.
| Verdict | Meaning | What to do |
|---|---|---|
| Failing | The last run failed. The dashboard is serving its last good numbers. | Troubleshoot it |
| Archived | Deliberately idle. | Nothing. |
| Paused | Deliberately idle. | Nothing. |
| Paused - plan lapsed | Runs are being skipped, not failed. | Upgrade, and it resumes on its own. |
| Not scheduled | The cadence is manual. It runs only when triggered. | Set a cadence if you want one. |
| Awaiting first run | Scheduled, never completed a run yet. | Wait for the next run, or use Run now. |
| Stale | The last good run is older than twice this dashboard's own period. | Troubleshoot it |
| Up to date | Refreshing normally. | Nothing. |
Stale is scaled to the dashboard, not to a fixed age. An hourly dashboard and a monthly one are judged on their own periods, so a daily dashboard that ran 26 hours ago still reads Up to date. The window is two full periods, which absorbs normal timing spread and one skipped run before it says anything.
Under the verdict sits the freshness line for the most recent run. Each state is
worded differently on purpose, so a failed or in-flight run never reads as
Updated 5m ago:
Updated 12m ago
Refreshing now
Last run failed 40m ago
Refresh paused
Relative times are compact throughout: just now, 12m ago, 2h ago, 3d ago,
2w ago. In the run history, hovering a run's Started cell or one of the
health-strip dots gives the exact timestamp.
The Next run column, and what it shows while failing
For a healthy schedule this is the next nominal run time. For a Failing row
it is the next retry, which is not the same thing: retries back off, so the
retry instant moves further out with each consecutive failure. When the retry is
imminent, or the server has not yet materialized an instant, the cell reads
Retrying shortly.
The ladder itself is on Failure alerts and retries.
Reading the History tab
History replaces the table with a newest-first feed of runs. Filter it by All, Succeeded, Failed, or Running. It loads 100 runs at a time.
You see runs for the dashboards you published, not the whole team's
Run history is readable only by whoever published a dashboard. Inside a workspace, the feed shows your own dashboards' runs rather than every member's, so an empty History tab on a team you know is active is expected rather than a fault.
get_refresh_status is the way round
it: it is workspace-capable, so any member can read a team dashboard's state and
its recent runs by slug.
Selecting a dashboard drills into that dashboard alone and adds a header with:
- the freshness line for its latest run,
N/M recent runs succeeded, over the most recent 30 runs. Runs still in flight and plan-lapse skips are excluded from both halves, because neither is a failure,- a strip of up to 10 dots, oldest on the left, one per recent run.
Each run row carries Status, Started, Duration, and Rows.
| Status pill | Means |
|---|---|
| Succeeded | The refresh completed and wrote data. |
| Failed | The refresh did not complete. The previous data was kept. |
| Running | In flight. |
| Paused | Skipped because the plan paying for this dashboard's refresh lapsed. |
Paused is neutral, not red, and does not count as a failure. The row is
recorded as a failed run carrying tier_lapsed, and every surface that reads it
de-reddens it on that basis: the pill, the dot in the health strip, and the
success ratio all treat it as neither a success nor a failure. See
what a lapsed plan actually does.
Two markers appear in the Rows cell:
- No change means the SQL re-ran and produced data byte-identical to the previous run. It is a healthy result, not a missed refresh. It appears only on an explicit determination, never when the comparison is unknown.
- A signed delta such as
+412or-8is the row-count change against the previous counted run of that dashboard. It is deliberately not colored: a shrinking cube is not a failure. It appears in the per-dashboard drill-in only, because counts from different dashboards are not comparable.
What a failed run tells you
A failed run expands into a detail line beneath it. What you see depends on where the failure came from.
A warehouse-backed run carries a classified reason and, for most classes, a remedy link:
| Class | Line shown |
|---|---|
connection_auth | Your warehouse rejected the sign-in. Reconnect it in Data sources to resume refreshing. |
connection_unreachable | The refresh could not use your warehouse data source. Reconnect it in Data sources to resume refreshing. |
connection_timeout | Your warehouse refresh timed out. A slow warehouse or a heavy query can cause this; check the data source in Data sources, or simplify the dashboard's query, then refresh again. |
ssl_failed | The secure connection to your warehouse could not be established. Reconnect it in Data sources to resume refreshing. |
schema_drift | Your warehouse schema changed since this dashboard was set up. Resync the data source in Data sources to map the current columns. |
cube_error | This dashboard's query did not complete against your warehouse. A schema or permission change, or a result too large to return, reports the same way as a query error. Check the recorded reason before republishing the query. |
connection_removed | The warehouse this dashboard refreshed from was removed. Reconnect a warehouse in Data sources to resume refreshing. |
tier_lapsed | Paused - the plan that pays for this dashboard's refresh no longer includes it. Refreshing resumes automatically once that plan is upgraded. |
cube_error does not mean your query is wrong
On the refresh path cube_error is the bucket a failure lands in when nothing
more specific claimed it. A genuine SQL fault, a permission change, a result too
large to return, and several of our own internal faults all report identically.
That is why the line names the alternatives instead of telling you to rewrite the
query, and why it is the one class with no remedy link.
Read the recorded reason under Show details before changing any SQL.
A class this build does not recognize falls back to a line that asserts nothing about the cause:
The scheduled refresh could not recompute this dashboard's data. Check the recorded reason for what failed.
A run against the built-in self source carries no class. It shows a plain
readable sentence instead, with the raw server text behind Show details.
The stored reasons for a warehouse failure are short and fixed. These are the literal strings a run records:
warehouse connection authentication failed
warehouse was unreachable
warehouse query timed out
warehouse TLS/SSL negotiation failed
warehouse cube query failed
data connection is no longer active
the plan that pays for this dashboard's refresh has lapsed; paused until it is upgraded
warehouse schema changed; cube query no longer matches
They never carry your warehouse's host, user, database name, or any driver text. That is deliberate: a run row is not a safe place to keep remote error output.
One reason is longer, and it is the one worth recognizing on sight:
island_unaddressable: the refreshed data is present but 3 declared keys would not resolve in it - main.month, main.ending_arr, main.__g_month. The previous data was kept. This usually means the statement's output column names no longer match the declared keys.
That run fetched real data and then refused to publish it, because the keys the dashboard reads would not have resolved and every tile would have rendered empty. Your previous numbers were kept. It usually follows a change to the column names your SQL returns.
Seeing what a run produced
A successful run that stored a snapshot gets a View button in its row. It opens that run's data exactly as it was written, so you can compare two runs, or compare one run against your warehouse, without republishing anything.
A run whose dataset offloaded to Parquet has no button, because there is no JSON snapshot to open.
To see the SQL behind a dashboard, use View query in its row on the Schedules table.
View query is personal dashboards only
The control is not rendered on a workspace dashboard's row, because the reader
behind it is owner-scoped. For a team dashboard, ask your AI instead:
get_source_config returns the same
compiled manifest and any member of the workspace may read it.
From your AI tool
Ask for the refresh status by slug, and your AI reads the same state plus the recent runs:
What is the refresh status of my arr-overview dashboard?
That calls get_refresh_status, which
returns the schedule, the next run, the consecutive-failure count, and the most
recent runs. It never triggers a refresh.
Check it worked
- Open dashies.xyz/app/schedules. The scheduler caption reads Scheduler active with a sweep within the last few minutes.
- The band either lists dashboards by name or collapses to the all-clear sentence. If it lists any, each one has a reason and a link.
- Open History and confirm runs are landing. The newest run's Started time should be no older than the shortest cadence you have set.
- Pick one successful run and click View. You should see the data that run wrote.