Rules / Maintenance
Measure defined in the report
What it checks
Measures defined in the report's reportExtensions.json rather than in the model, reported when the model the report reads is in the input, so that each can move into it.
Each finding names the measure, as [Sales per Region] (report), at the line where its entry opens in reportExtensions.json, and its detail names the table it is defined on: defined in the report on table "Sales".
Example
The example runs against a model with one table, Sales, holding Amount and Region and the measure Total Sales.
reportExtensions.json{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definition/reportExtension/1.0.0/schema.json",
"name": "extension",
"entities": [
{
"name": "Sales",
"measures": [
{
"name": "Sales per Region",
"dataType": "Double",
"expression": "DIVIDE([Total Sales], DISTINCTCOUNT('Sales'[Region]))"
}
]
}
]
}
{
"definition/report.json": {
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definition/report/3.2.0/schema.json",
"themeCollection": { "baseTheme": { "name": "Fluent2-CY26SU04", "type": "SharedResources" } }
}
}
The report defines Sales per Region for itself, on the Sales table, so the finding reads [Sales per Region] (report) with defined in the report on table "Sales". The fixed report shows its side of the move: once the measure is in the model's Sales table, as How to fix it describes, the report defines none, and its definition folder holds no reportExtensions.json, since Power BI Desktop does not open a project whose reportExtensions.json has an empty entities list.
Why it matters
A report measure is a calculation created directly within a report, without altering the semantic model, so the model never carries it and only the report that defines it can use it. Another report on the same model does not have it. When the model is in your hands, as it is when the report reads it by path from the same project, a calculation kept in one report splits the model's logic in two: the next author looking for it in the model does not find it, and a second report that needs it gets a copy of its own, free to drift from the first.
pbiplint checks such a measure less well too. Its DAX rules read the model's measures only, so none of them looks at a report measure's expression, and BROKEN_FIELD_REFERENCE does not report a field that a report measure's DAX names and the model lacks.
How to fix it
Move the measure into the model with the same name, on the same table, with the same DAX, then point the report at it. How depends on how the report reads its model.
If the project opens its model by path, as the sample does, the fix edits one report file, which only PARSE_ISSUE's page also asks for among the report pages. Power BI Desktop shows the report measures in such a project, but its menu fails on them, so it cannot rename or remove them (checked in Power BI Desktop 2.158, September 2026).
- Note each report measure's DAX and any format it sets. A report measure that another one uses moves with it: in the sample, Margin % (report) uses Net Margin.
- With Power BI Desktop closed, delete their entries from reportExtensions.json, and an entity when it holds no measure any more. When no measure is left, delete the file itself: Desktop does not open a project whose reportExtensions.json has an empty
entitieslist (checked in Power BI Desktop 2.158, September 2026). - Open the project in Power BI Desktop and create each measure with New measure on its table, with the same name and DAX: right-click the table in the Data pane, or hover over it and select More options (...), choose New measure, and type the name and the DAX into the formula bar (Create a measure (opens in a new tab)). In such a project the measure is saved in the model's TMDL (checked in Power BI Desktop 2.158, September 2026).
- Put the model's measure in each visual, filter, and bookmark that used the report measure, as step 4 of the route below describes. A visual stays broken until the measure is added again, and a sort on the measure follows it back (checked in Power BI Desktop 2.158, September 2026).
- Save the project and lint again:
BROKEN_FIELD_REFERENCEnames any reference left.
If the report connects live to a published model and you can change the model, in Power BI Desktop:
- Open the report so that it connects live to the published model, through the .pbir file When to ignore it describes. Note the measure's DAX and any format it sets, then rename it so the model's measure can take its name: right-click it in the Data pane and select Rename. Checked in Power BI Desktop (version 2.158, September 2026), a report measure's menu in a report connected live to a published model has Rename and Delete from model. Microsoft's schema for report measures asks that a report measure's name be unique across the model, so the two should not exist side by side under one name.
- Open the model itself in Power BI Desktop, from its own project or file: in a report that connects live to a model, "left navigation and modeling are disabled" (Connect to semantic models in Power BI (opens in a new tab)). Right-click the table in the Data pane, or hover over it and select More options (...), choose New measure, and type the name and the DAX into the formula bar. Microsoft notes that this "saves your new measure in the Sales table" for its example (Create a measure (opens in a new tab)), so a measure created from a table's menu is saved in that table.
- Publish the model. Republishing replaces the semantic model in the service (Republish or replace a semantic model (opens in a new tab)), and "any changes to the semantic model reflect in the report" (Connect to semantic models in Power BI (opens in a new tab)).
- Back in the report, put the model's measure wherever the report measure was: drag it from the Data pane into each well in place of the renamed one (Create your first visualizations (opens in a new tab)), into the Filters pane in place of each filter on it (Add a filter to a report (opens in a new tab)), and, for a visual sorted by it, choose it under More options (...), then Sort axis (Change the visualization type (opens in a new tab)). For each bookmark that captured it, select More options (...) next to the bookmark's name and choose Update (Create report bookmarks (opens in a new tab)).
- Delete the renamed report measure: right-click it in the Data pane and select Delete from model, the item step 1's check found on the same menu.
Lint again when you are done. A well, filter, sort, or bookmark that still names the report measure after step 5 is reported by BROKEN_FIELD_REFERENCE.
If you cannot change the model, keep the report measure: it is the supported route for an author who cannot change the model, as When to ignore it says.
When to ignore it
A report measure is the supported route for an author who cannot change the model, and such a report can still reach pbiplint beside the model. When the model and the report share a workspace, Fabric Git integration always exports the report with a reference by path to the model. Microsoft describes keeping a second .pbir file that connects to the published model, so that the report opens in live connect to work with report-level measures, while definition.pbir, the file pbiplint reads, keeps its reference by path. If that is how the report is built and the model belongs to someone else, ignore the finding. When the model is yours to change, a measure rarely has a reason to stay in one report.
This rule reports on measures defined in the report, and pbiplint reads no annotation on them, so there is no object to annotate. To turn the rule off for a whole project, set "REPORT_LEVEL_MEASURES": "off" under rules in pbiplint.config.json.
Quirks
- The rule reports only when the model the report reads is in the input. A report whose definition.pbir connects to a published model is left alone on purpose: Microsoft presents report measures as the way an author who builds on a shared semantic model through a live connection, which cannot change the model itself, adds calculations of their own. Such a report is linted without a model, as is a report given on its own, and the skipped line gives the reason, such as
this report reads a published modelorthis report reads ../Sales.SemanticModel, which this run did not include. - pbiplint reads no annotation on a measure in reportExtensions.json, so the rule is turned off for a whole project rather than for one measure.
- A measure with an empty expression is reported like any other.
- As of Power BI Desktop 2.158 (September 2026), a report measure in a project that opens its model by path shows in the Data pane, but right-clicking it shows an error rather than its menu, so How to fix it removes it from reportExtensions.json for such a project. Once Desktop's menu works there, the Desktop route for a report connected live to a published model applies to such a project too, and the file step can go.
Related rules
BROKEN_FIELD_REFERENCEresolves a reference to a report measure while the report defines it, and reports one still naming the report's extension after the measure has moved.NOT_REACHED_FROM_REPORTcounts the fields a report measure's DAX names as reached, so moving a measure that no visual shows into the model can put the measure on that rule's list.
Links
- Power BI Desktop project report folder, where reportExtensions.json holds report-level measures (opens in a new tab)
- Measures in Power BI Desktop, including report-level measures (opens in a new tab)
- Tutorial: create your own measures in Power BI Desktop, including New measure on a table (opens in a new tab)
- Managed self-service BI, the usage scenario where report creators build on a shared semantic model and create report-level measures (opens in a new tab)
- Connect to semantic models in Power BI, including what a live connection lets a report author create (opens in a new tab)
- Microsoft's reportExtension schema, the shape of reportExtensions.json and of a report measure's references (opens in a new tab)
- Microsoft's semanticQuery schema, where a SourceRef names its schema and entity (opens in a new tab)
Check a report for this Improve this page (opens in a new tab)