A best-practice checker is a list of rules: give every measure a format, set relationships to filter in one direction, move calculated columns to Power Query. Most of the time each rule is right. But Microsoft's own documentation lists exceptions to several of them, and a checker that ignores the exceptions gives advice you cannot follow, or should not.
We found that out about our own Model Health Check. We ran it on 23 models and labelled every finding true or false against Microsoft's documentation. Before the fix, 206 of 5,656 findings we could judge were wrong (96.4% right). Every one of the 206 was a rule applied where it does not fit, and for the clearest cases Microsoft's own pages say so. After the fix, 1 of 5,464 is wrong (99.98% right). These are the five exceptions, so you can apply the rules the way Microsoft means them, with any tool.
1. A text measure needs no number format
Microsoft's Best Practice Analyzer asks for a format string on every visible measure. A format string tells Power BI how to show a number: a percent sign, decimals, a thousands separator. A measure that returns text, like a dynamic title, a button label or a "Data as of" line, has no number to format.
This was our biggest mistake: 148 of 338 "no format" findings were text measures. The patterns that return text are easy to miss: SELECTEDVALUE of a text column, a CALCULATE around a text measure, an IF whose branches are all text. If your checker lists such a measure, leave it. On a number, though, the rule matters: a margin of 33.8% with no format shows on a card as 0.34.
2. A one-to-one relationship filters both ways, and must
Microsoft's bi-directional relationship guidance says to minimize relationships that filter in both directions, because they can slow queries and confuse report users. The same page names the exceptions. For one-to-one: "All one-to-one relationships must be bi-directional—it isn't possible to configure otherwise." And between two dimensions linked through a bridge table, "A bi-directional filter is required to ensure filters propagate across the bridging table."
11 of our 57 findings told people to set a one-to-one relationship to single direction, which Power BI does not allow. A twelfth flagged an inactive relationship: its direction costs nothing, because it filters nothing until USERELATIONSHIP turns it on. Now the check leaves one-to-one alone and, for a bridge, asks you to confirm that it is a bridge instead of telling you to change it. For any other both-direction relationship, Microsoft suggests the CROSSFILTER function inside the one measure that needs it.
3. Some calculated columns belong in DAX
Microsoft's data reduction guidance prefers columns added in Power Query or at the source: calculated columns typically compress less well and are built only after every table has loaded. Then it adds: "However, in some instances, model calculated columns might be the better choice. That's true when the formula involves evaluating measures, or it requires specific modeling functionality only supported in DAX functions."
10 of our 44 findings were columns of that kind: a running total with EARLIER, a rank with RANKX, a parent-child path with PATH, a value that sums another table. A simple IF, a text join or a RELATED lookup still belongs in Power Query; a merge does the same job there.
4. FILTER is right when the condition is a measure
Microsoft's DAX guidance says avoid FILTER as a filter argument: write KEEPFILTERS('Product'[Color] = "Red"), not FILTER('Product', ...). But a Boolean filter "Cannot reference a measure", so for "sales in months with a profit" Microsoft itself writes:
Sales for Profitable Months =
CALCULATE(
[Sales],
FILTER(
VALUES('Date'[Month]),
[Profit] > 0
)
)
Our check used to say "filter the column instead" here too, which cannot work. It now tells the two cases apart. A column condition: use a Boolean filter. A measure condition: keep FILTER, but over VALUES of one column, as above, not over the whole table. None of our 23 models had this case; we found it reading Microsoft's page, and it now has its own test.
5. A hidden measure needs no description
The Best Practice Analyzer asks for descriptions on visible objects, because Power BI Desktop shows a description when you hover the field in the field list. A hidden measure is not in the field list, so nobody sees its description. 26 of our 1,132 "no description" findings were hidden helper measures, and so were 5 "no display folder" findings and 1 "no format" finding: a folder only organizes the field list, and a format only shows in a visual, which a hidden helper is not in. Describe and file what report authors use; the helpers can wait.
The rest, and what a file cannot tell
The last 4 wrong findings were smaller, and fixed too. Two "date table not marked" findings were date pickers (one date column, no relationship), not calendars. One "hard-coded path" was a {{...}} placeholder filled in at deployment. And one "duplicate measure" was two measures with the same text, SUM([SalesAmount]), in two tables: each sums its own table, so they are different. Microsoft's Best Practice Analyzer compares the text too, and makes the same mistake.
47 findings we could not label, and the tool says so instead of guessing. Whether a model needs row-level security depends on who will use it (21 models with no security roles). Some broken report references can only be confirmed by opening the report in Power BI Desktop (19). Five more are judgment calls the file cannot settle: a CALENDARAUTO date table and long Power Query steps. The one wrong finding left is a text column built with SELECTCOLUMNS and INDEX that the format check does not yet read as text; it is on our list.
How we measured
The 23 models: 18 published by Microsoft on GitHub under the MIT licence (from fabric-toolbox, Analysis-Services, fabric-samples, fabric-cicd and powerbi-desktop-samples), pinned to exact versions, and 5 test models of our own. The check ran in Node on each file. Each of the 5,703 findings was labelled true or false against Microsoft's documentation, or unsure when the file alone could not decide; after the fix, the same labels were used again. The precision is the true findings divided by all the findings we could judge. One effect you can see on our site: Microsoft's COVID-19 sample now scores 85 instead of 84.
What to take from this
- Read the reason, not only the rule. Every finding in the Model Health Check now names its source: the Microsoft page, the Best Practice Analyzer rule, or "DataArcus rule" with why.
- Before you change a model because a checker said so, check the five cases above. They are the common ones where the rule does not apply.
- Run it on your own model: File > Export > Power BI template, then drop the .pbit on the Model Health Check. It runs in your browser; nothing is uploaded. For the steps that make a model ready for Copilot, see our 7-point check.