Skip to content

View reports

The Reports workspace is a two-pane screen at /reports that gives you a bird's-eye view of your library's health, compliance, and metadata state. The left rail lists every available report; the right pane renders the one you select.

Open the Reports workspace

Click Reports in the sidebar. The workspace opens with the Compliance overview active by default. You can also navigate directly to /reports/{report-name} (for example, /reports/health).

The reports rail

The narrow rail on the left lists all built-in reports. A filter box at the top of the rail lets you type to narrow the list by name. Click any entry to load it in the right pane - the active entry is highlighted and the URL updates to match.

Live reports

Six reports have fully implemented right panes:

Compliance overview

Shows field and rule coverage across your library as a paginated artist table. You can search, filter by status, library, or health-score range, sort by any column, and export the current view to CSV.

The pane has two tabs:

  • Results - the standard compliance list with per-artist health scores and violation counts.
  • Matrix - a scrollable rule-by-artist compliance matrix for an at-a-glance view of which rules pass or fail across the catalog.

Use the Run button to refresh the pane from the latest data without navigating away.

Library health

Shows a compliance score summary, total and compliant artist counts, a breakdown of missing metadata types (NFO, thumb, fanart, MBID), and a ranked list of the top failing rules with per-rule pass rates.

Metadata completeness

Shows field-coverage percentages across your entire library and a table of the ten artists with the lowest completeness scores, broken down by library.

Rule pass rates

Lists every configured rule with its pass count, evaluation count, and pass percentage for the current library state. Pass rates are color-coded: green at 80% or above, amber between 50-79%, and red below 50%.

Blast radius

The blast-radius report answers "which values that I set did an automated change replace or blank". Click Blast radius in the reports rail to open it. The same rows are also available as a CSV spreadsheet, though only through the API for now - see Downloading the CSV below.

For each artist and field, the report shows the most recent change, and keeps it only when that change replaced or blanked a value that had been set. Two kinds of damage are reported, because both destroy what you set:

  • Blanked - a value you had was emptied.
  • Replaced - a value you had was overwritten with a different one.

A field whose value has since been put back drops out of the report automatically.

You can narrow the report by damage kind, by attribution, by field, or to a single artist. Both damage kinds are shown by default. The pane does not yet offer on-screen filter controls, so for now you set a filter by adding it to the page address; the pane reads the filters from the URL and keeps them as you page through results. The CSV download accepts the same filters. The API reference lists the exact filter names and values.

When a filter matches nothing, the pane says so and tells you how many changes the report still holds behind that filter. It does not report an all-clear, because a filter matching nothing says nothing about the rest of your library.

Putting a value back

Every row in the workspace pane has a Restore button that writes your old value back over what the automated change left. You can also tick the checkbox on several rows and use Restore Selected to put them all back in one go. The checkbox in the header ticks every row on the page you are looking at; because the report is paged, it cannot reach rows on other pages.

Restore is always two steps, and the first one never writes:

  1. Preview. Stillwater checks each selected row against the current state of your library and reports how many of them can be put back, and how many cannot. Nothing has been written at this point.
  2. Confirm. Only then does the write happen, and only for the rows the preview listed as restorable.

A preview is not a promise. Stillwater re-reads each value immediately before writing it, because a scan, a rule pass, or an edit you made in another tab can land in the gap between the preview and your confirmation. If the value changed in that gap, the restore is refused rather than overwriting the newer value with an older one. A row is also refused when the change record is gone, when the field keeps no change history, or when the row is itself an earlier restore, which would only chain undo onto undo.

That means a confirmed restore can come back reporting fewer values put back than the preview offered, including none at all. Stillwater tells you which happened:

  • All rows restored - a success message with the count.
  • Some restored, some refused - a warning naming both numbers. The restore is incomplete.
  • Nothing restored - an error message with the refusal count.

Refused rows stay in the table so you can see they still need attention; only rows that were genuinely put back disappear from it. A refused restore is safe to retry: reload the report so it reflects the current state, then try again.

Restoring a value does not republish it or re-run the writer that changed it. It does mark the artist for re-evaluation, so the next rule pass looks at it again. Only one restore can run at a time across the whole application; if another is already in progress, Stillwater says so instead of queuing yours.

What the report can prove about who made a change

Every row is labeled one of two ways:

  • Automated - written by a scan, an import, a metadata provider, or a rule. The source was recorded, so this is certain.
  • Unknown - anything Stillwater cannot positively identify as an automated writer, so nothing falls outside the two counts. Most of these are recorded as a manual change. Stillwater began recording scan-driven changes separately on 2026-07-19; before that, a scan that changed a value was recorded the same way your own edits are. These rows may be your edits or may be automated changes, and Stillwater cannot tell them apart.

Rows with unknown attribution are always listed and always counted separately. Narrowing the report to automated changes hides those rows from the list but does not remove them from the counts, so you can always see how many there are. A number that quietly excluded them would understate what was lost.

What the report covers

Only fields that keep a change history can be reported. The response lists both the covered and the uncovered fields.

Several editable fields keep no change history on the scan path, including disambiguation, name, and sort name. A field's absence from this report is not evidence it is undamaged if it is on the uncovered list - it means Stillwater has no record either way.

How far back it goes

Change history is not deleted on a schedule, so the report reaches back as far as your history goes.

It is not unlimited, though: change history is kept until an artist is deleted or merged into another. Either removes that artist's history along with it, including anything this report would have shown for it. If you are cleaning up duplicate artists, run this report first.

Downloading the CSV

The CSV carries the same rows plus the source label on each one. Note rows at the end restate the source limit, both field lists, and the retention boundary, so a spreadsheet you open weeks later still says what it does not cover. The export is capped at 10,000 rows and tells you when it was truncated.

There is no download button on the pane yet, so this export is reachable only through the API. The API reference has the endpoint and its parameters.

Rule-Written MusicBrainz IDs

This report answers "which artists did the automatic NFO rule fix pick a MusicBrainz ID for". It exists so you can find artists that fix may have misidentified. Click Rule-Written MusicBrainz IDs in the reports rail to open it, right next to Blast radius - both are automated-write reports the rail groups together. The same rows are also available as a CSV spreadsheet or as raw JSON through the API; see Downloading the CSV below.

Each row is one ID assignment: the artist, the current MusicBrainz ID it carries, the note the fix recorded at the time, and when it happened. If the fix wrote an ID for the same artist twice, you get two rows, because each one was a separate guess worth seeing. Every row has a Review link straight to that artist's page, since deciding whether a guessed ID is right means looking the artist up. You can narrow the report to a single artist by adding ?artist_id= to the page address, the same way the blast-radius pane's filters work; the API also lets you sort by date or artist name.

The pane's caveat band sits directly under the report title, always visible - never behind a toggle you have to open. Read it before trusting the count: this report is a floor, not a census, and the reasons why are below.

Read-only. This report does not contact MusicBrainz, does not check whether an ID is correct, and does not change or undo anything. Deciding what to do about a row is yours.

It filled blanks; it did not overwrite your IDs

This fix only ever ran on artists that had no MusicBrainz ID, so it never replaced an ID you had set. Every row is a blank field filled in with an ID that may be wrong. That is why there is no previous-value column: there was never a previous value.

What the report cannot see

This report covers the automatic NFO rule fix only. The automatic match steps of the Identify flow can also assign a MusicBrainz ID and record no change at all, so artists they affect can never appear here, however long the report runs. The bulk rule run now records its own assignments too, but under a different, more specific label, so this report still will not list them, even though a record of them does exist and can be found on the artist's own history. So for the Identify flow this is a permanent limit of what is recorded; for the bulk rule run it is a scoping choice this report makes, not a gap that cannot be closed.

Two consequences worth stating plainly:

  • This list is not the complete set of machine-assigned MusicBrainz IDs.
  • An artist's absence from this list is not evidence that a person chose its ID. Stillwater does not yet record operator confirmation of a MusicBrainz ID, so "not on the list" means only that this particular fix did not write it.

The counts are a minimum

Treat every count as a floor. Change history is kept until an artist is deleted or merged into another; either removes that artist's history along with it, including rows this report would have shown. A known side effect of these misidentifications was duplicate artists, so some affected artists have probably already been merged away and cannot be counted at all. The real number is at least as large as the number shown, and may be larger.

Reading the recorded note

The note is shown exactly as it was written at the time, and Stillwater never tries to interpret it. Two wordings exist:

  • Older entries record only the ID and the artist name.
  • Newer entries also record the matched name, where the match came from, the confidence score, and the runner-up.

When you act on a row, use the current MusicBrainz ID, not the note. The ID in the note is what the fix wrote then; the artist may carry a different one now, or none at all. An artist with no MusicBrainz ID recorded today is shown as "none recorded" rather than left blank, because a blank cell reads as nothing to see.

Downloading the CSV

Click Export CSV at the top of the pane, or reach the same file directly through the API. The CSV carries the same rows. Note rows at the end restate every limit above, so a spreadsheet you open weeks later still says what it does not cover. The export is capped at 10,000 rows and tells you when it was truncated.

Additional reports

Six further reports appear in the rail and are coming in a future release:

Report What it will cover
Underrated artists Artists with strong library presence but a low health score
Image coverage Thumb, fanart, logo, banner, and backdrop coverage
Connection sync Where each artist is registered across connected platforms
ID/Metadata coverage Per-provider linking and metadata status
State records Artist lifecycle and refresh history
Weekly review queue Artists scheduled for manual review

Duplicate and foreign-file reports

The sidebar's Reports group also lists Duplicates, Backdrop Duplicates, and Unmatched Images. These are dedicated pages at their own URLs (/reports/duplicates, /reports/backdrop-duplicates, /reports/foreign-files), not entries in the two-pane workspace's rail. The Duplicates and Unmatched Images pills show a live count when there's something to review. See Merge duplicate artists for the duplicate-detection and merge workflow.

Backdrop duplicates

The Backdrop Duplicates report finds cases where the same backdrop picture has been written into several of one artist's backdrop (fanart) slots. This commonly happens when a media server's own image fetcher saves the same artwork under many tags, so one artist ends up with the same image repeated across fanart.jpg, fanart2.jpg, fanart3.jpg, and so on. It is an admin-only page; click Backdrop Duplicates in the sidebar's Reports group to open it.

The report scans every artist's backdrops on disk and finds exact duplicates: byte-for-byte identical files, matched by a content hash. Because a removed copy is identical to the one kept, collapsing them loses nothing.

That scan reads every backdrop file in the library, so it runs in the background on a schedule rather than each time you open the page. The report shows the result of the most recent scan, with the time it was taken, so the numbers are a recent snapshot rather than a live count. The alternative would be re-reading the whole library on every page load, which on a large or network-stored library takes minutes.

If no scan has completed yet -- on a first run, or before the first scheduled refresh -- the page says the report is still being prepared and starts a scan in the background. Reopen the page once it finishes. The page deliberately does not show zeros in that state, because "nothing has been measured yet" and "your library is clean" are different answers.

The page summarizes how many artists are affected and how many exact redundant slots exist, with a per-artist breakdown. If some artists could not be scanned, a Partial Scan notice reports how many were skipped, so a partial result is never mistaken for a clean library.

Collapse exact duplicates

Click Remediate Exact Duplicates to collapse the exact (byte-identical) redundant slots across the whole library in one pass. For each affected artist, the lowest-numbered backdrop slot is kept and the identical copies are removed, with the remaining backdrops renumbered into a gap-free sequence.

Remediation is safe by design:

  • A backdrop you set or locked yourself is never removed -- operator-curated artwork is protected from this tool.
  • An artist always keeps one copy of each distinct backdrop; the tool only removes proven duplicates.
  • Only one remediation runs at a time, and it will not run while a bulk image action is in progress, so the two can never touch the same files at once.

Only the copies stored locally are collapsed; backdrops already pushed to a connected platform are not removed by this action.

Perceptual duplicates

Some redundant backdrops are visually near-identical but not byte-for-byte the same file -- the same picture saved twice at different quality or resolution, for example. The exact-duplicate scan cannot see these, because it matches by content hash, and a re-encoded copy hashes differently even though it looks the same on screen.

Remediation reports these separately from the exact count it just collapsed, rather than folding them together. A run that removed only the byte-identical minority and left the look-alike majority in place should never read as a clean sweep -- "removed" and "declined to remove" are different outcomes, and the report keeps them distinguishable. This also means a re-run that appears to do nothing can be told apart from one that genuinely had nothing left to do: the first still shows a perceptual count, the second shows none.

If remediation has never run, or no report has ever measured perceptual redundancy, the count is shown as unknown rather than as zero -- an unmeasured library is not the same claim as a clean one.

Platform backdrop duplicates

Platform sync is additive: pushing fanart to a connected media server never deletes a surplus copy on that server, so a redundant slot that the local Backdrop Duplicates report already cleaned up on disk can still linger on Emby or Jellyfin. The Platform Backdrop Duplicates report finds those leftover copies directly on your connected platforms. It is an admin-only page at /reports/platform-backdrop-duplicates.

The report re-reads every artist's backdrops from each connected platform and finds exact duplicates: byte-for-byte identical files, matched by a content hash, the same standard the local report uses. It is a dry-run: opening the page only scans and summarizes, nothing is deleted until you choose to prune.

The page summarizes how many connections and artists are affected and how many redundant backdrops exist, with a per-artist, per-platform breakdown. If some artist/connection scans could not complete, a Partial Scan notice reports how many were skipped, so a partial result is never mistaken for a clean sweep.

Prune platform duplicates

Click the prune button to delete the exact (byte-identical) redundant backdrops across every connected platform in one pass, keeping one surviving copy per artist per platform. The prune re-scans each platform immediately before deleting, rather than trusting the report you're looking at, so it never acts on a stale count. Only one prune runs at a time; starting a second while one is in progress is rejected rather than allowed to overlap.

Because the prune only ever removes copies that are byte-identical to a kept survivor, no distinct artwork is ever lost. If a platform's copy is later needed again, re-running fanart sync from the local library re-pushes it from the local survivor.

Cross-artist backdrop pollution

Where the two duplicate reports above find the same backdrop repeated within one artist, this report finds the harder case: a backdrop that belongs to one artist has bled into a different artist's backdrop slots. This happens when a media server's image fetcher saves an artist's promo shot under the wrong artist, so the picture ends up mirrored across two artists' fanart. The report matches backdrops by visual near-similarity (a perceptual hash) rather than byte-for-byte, because a re-encoded or resized copy is no longer byte-identical but is still the same picture in the wrong place.

Because the signal is a visual match, it is inherently ambiguous: two artists can legitimately share a picture (a duo, a collaboration, a festival photo), which looks identical to pollution. Every action below is built to absorb that ambiguity rather than assume it away, which is why the back-out is designed to be undone.

Back out polluted backdrops

Remediation quarantines each flagged backdrop, removes it from the artist locally, and deletes the mirrored copy from your connected platforms. It is admin-only.

This report has no screen of its own: unlike the two duplicate reports above, there is no page to open and no button to click. You run the back-out through the API, which is where the API reference documents the request in full. What it asks of you is worth knowing before you run it:

Option Meaning
Artist Scope the back-out to a single artist.
All artists Run library-wide. You must choose one scope or the other - a request with neither is rejected, so a forgotten scope can never become a library-wide delete.
Dry run Preview the outcome without changing anything.
Tolerance Optionally override the similarity cutoff, as a number above 0 and no greater than 1. Anything else is rejected rather than quietly falling back to the default.

Remediation is designed to be safe on an ambiguous signal:

  • It re-detects fresh from the current library at the moment it runs, never acting on a report that may have gone stale since you viewed it.
  • Before removing any backdrop it re-checks the picture against the bytes on disk - both the suspect and the artist it collided with - and skips anything that no longer confirms the match.
  • It copies the picture into a durable quarantine before removing the original, so a removed backdrop is always recoverable.
  • The platform-side delete happens only after the local removal has committed; the fuzzy platform match never authorizes a deletion on its own.

The response summarizes how many artists were processed, how many slots were removed, quarantined, or skipped, and any failures, with a per-slot breakdown. On a dry run, slots are reported as "would-remove" and nothing is touched. Each run is tagged with an operation id - keep it if you may want to restore the run later.

Restore a back-out

If a back-out removed a backdrop that was not actually pollution, the restore puts that operation's quarantined backdrops back - both locally and on the platforms they were deleted from. It is admin-only.

The restore runs through the API too, and needs two things: the artist, and the operation id from the back-out run you want undone. A request missing either one is rejected, so a restore can never guess which run you meant. The API reference has the request itself.

Restore is content-addressed: it appends a recovered backdrop at the next free slot rather than trying to put it back at its old position, because removal renumbers the survivors and the old position no longer exists. Appending can never overwrite another backdrop. Each quarantined picture lands in one of three states, reported separately so a restore that needs your attention is never mistaken for a clean one:

  • Restored - the backdrop was written back to disk.
  • Already present - a byte-identical copy was already there, so nothing was needed.
  • Needs review - a surviving backdrop only resembles the quarantined one but is not identical, so the restore was declined and the quarantined copy is kept for you to settle by hand. This is deliberately not counted as success.

One repair at a time

Both actions, the two duplicate remediations above, and any bulk image action all share a single lock: only one runs at a time, and starting one while another is in progress is rejected with a "backdrop repair or bulk action is already in progress" response rather than allowed to overlap. They all rewrite an artist's backdrop files on disk, so this keeps two runs from ever touching the same files at once.

Background appearance

The card surfaces in the Reports workspace follow the Background Opacity preference. See Customize preferences to adjust the frosted-glass opacity of cards and panels.