PL-300 common mistakes
PL-300 · Understand the traps and how to avoid them.
Applies transformations in whatever order the Applied Steps pane suggests - renames a column only at the end of the query, or inserts a filter below the 'Changed Type' step - so earlier downstream steps fail on the old name and the candidate patches it by stacking new steps on top of broken ones.
The Applied Steps list looks like a to-do checklist of independent toggles, but each step consumes the output of the step above it; late renames and out-of-order type changes break every step that already references the column.
What to do instead
Rename and remove columns immediately after the source step, put filters, splits, and type changes after that, and edit the existing step (gear icon) instead of appending a compensating step; walk the preview top to bottom to confirm each step still returns the expected rows and column names.
Accepts the auto-detected data type on flat-file sources without checking locale, so dd/MM/yyyy dates arrive as text or with day and month swapped, and decimal commas come in as text that cannot be summed later in the model.
The plain 'Change Type' action uses the file or profile culture, and the preview of a column headed 'Date' looks plausible until a value after the 12th of the month appears.
What to do instead
For every date and decimal column use Change Type > Using Locale and set both the target type and the correct locale, then sanity-check a row whose day is greater than 12 and confirm the column icon shows a date/number type before loading.
Uses Merge when the task is to stack same-shaped monthly extracts, or appends tables whose column names differ and ends up with surplus columns full of nulls.
Merge and Append sit together in the Combine group and both 'combine two tables'; Append matches on column name rather than position, so a mismatch silently produces extra columns instead of an error.
What to do instead
Append for same-schema stacking (rename to identical column names first, then confirm the row count equals the sum of the sources), Merge only when joining on a key column, and check the resulting column list after either operation.
Loads a single wide flat table, or relates a fact table directly to another fact table, then fixes filtering that does not propagate by flipping relationships to 'both' cross-filter directions or to many-to-many cardinality.
The default new relationship is single-direction and the model view gives no warning that a denormalized design is the real cause, so bidirectional filtering is used as a patch.
What to do instead
Build one dimension table per entity with a unique key, relate each dimension to the fact single-direction (dimension filters fact), and handle the rare genuine exception inside a measure with CROSSFILTER or USERELATIONSHIP rather than in the model diagram.
Creates a calculated column for a ratio or year-to-date figure that must respond to slicers, or writes a measure that references a bare column and hits 'Cannot determine a single value for column' errors.
Calculated columns and measures are created from the same New Column / New Measure buttons, but a calculated column is evaluated at refresh in row context and is fixed thereafter, so it never sees the report's filter context.
What to do instead
Use measures for anything that must react to slicers and filters, use calculated columns only for row-level attributes placed on axes, slicers, or relationship keys, and express ratios as DIVIDE([Measure], CALCULATE([Measure], REMOVEFILTERS(...))) or similar explicit filter-context logic.
Writes TOTALYTD, DATESYTD, or a prior-year comparison directly against the date column in the fact table, relying on the automatic date tables, and gets blanks or wrong year boundaries when the fact has more than one date column or date gaps.
Auto date/time generates hidden per-column tables that work in trivial demos, so the time-intelligence failure only appears with multiple dates, gaps, or a date range that does not cover the reporting period.
What to do instead
Create a dedicated date table with a contiguous date column spanning the full fact range, mark it as a date table, relate it to the fact's date column, and use only that table's columns as the date arguments in time-intelligence functions.
Adds a slicer and assumes it filters everything on the canvas, without checking that a visual has its own visual-level filter or that Edit interactions has been used to make one visual ignore another.
Filter precedence (visual, then page, then report) and cross-highlight versus cross-filter behaviour are invisible on the canvas, so a non-responsive visual looks like a bug rather than a settings hierarchy.
What to do instead
For the visual that misbehaves, read the Filter pane top-down (visual-level first, then page, then report), and use Format > Edit interactions to set filter, highlight, or none for each visual pair involving a slicer.
Drops a numeric field into a visual and accepts the default summarization, so an ID, a year, or a ratio is summed, a 'total' is a sum of averages, or a distinct-count question is answered with a row count; high-cardinality categories are then put in pie charts.
Default summarization is applied silently and the aggregation is not shown on the axis or card title, so the wrong number looks identical to the right one until someone adds up the rows by hand.
What to do instead
Set the aggregation explicitly in the field well (Average, Distinct count, Don't summarize), confirm the aggregation is visible in the visual title or tooltip, and choose the visual from the question type: line for time, bar for ranked categories, matrix for hierarchies, and avoid pies beyond a handful of slices.
Defines row-level security roles in Desktop but validates them only by signing in as a real user, and assumes a role restricts everyone in the workspace, including Admins and Members.
Role membership is assigned in the service rather than in the file, and workspace roles with edit rights on the dataset see all data regardless of RLS, so a passing spot-check hides both leaks and over-restriction.
What to do instead
Test each role with View as role in Desktop and Test as role in the service against a matrix containing the RLS field, remember that Admin, Member, and Contributor (with edit rights) bypass RLS, and prefer a dynamic role driven by USERPRINCIPALNAME() joined to a security mapping table over hard-coded email lists.
Confuses the distribution mechanisms - shares a report directly when the requirement is a packaged app, grants Build on a dataset when read-only consumption was requested, or schedules refresh without first checking gateway and data source credentials.
Workspace roles, app audiences, dataset permissions, and share links are four separate systems, and refresh depends on a gateway for on-premises sources plus stored credentials for every source, none of which the publish dialog surfaces.
What to do instead
Map requirement to mechanism (app for broad read-only distribution, workspace role for collaboration, direct share only as an exception), review the 'Allow recipients to...' options before sending, and after publishing verify Settings > Gateway connection and Data source credentials before enabling scheduled refresh.