Power BI PBIP Report Authoring
Create and modify Power BI reports in PBIR (Power BI Enhanced Report) format — the
file-based report definition used in PBIP projects. This skill produces and edits the
.Report/ folder with all JSON files that Power BI Desktop and the Power BI service can
open directly. It also handles live Desktop verification via screenshot workflows.
Input: A Design Spec from the power-bi-report-design skill (or equivalent user instructions)
specifying pages, visuals, layout positions, theme, and navigation.
Canvas size: 1664 × 936 (standard Power BI canvas). Tooltip pages: 320 × 240.
Must/Prefer/Avoid
MUST
- Use CLI capability lookup (
powerbi-report-author catalog/formatting) before writing
visual roles, formatting objects, enum values, selectors, or expression encodings.
- Validate PBIR with
powerbi-report-author validate after each logical batch of edits.
- Use
powerbi-desktop reload/screenshot workflows for rendered-output changes.
- Never guess PBIR JSON from memory when CLI metadata or reference files are available.
PREFER
- Start from an approved Design Spec or
Design Brief: for greenfield report builds.
- Route visual-design uncertainty to
power-bi-report-design before writing files.
- Use the Edit → Validate → Reload → Screenshot loop for any visual change.
AVOID
- Do not create legacy visual types (
card, table, matrix, map, filledMap).
- Do not hardcode property names without CLI confirmation.
- Do not skip Desktop verification for visual changes.
Reference Files
| Reference |
When to Read |
references/folder-structure.md |
Understanding the full PBIR folder layout |
references/powerbi-desktop.md |
Desktop verification — open, reload, screenshot, PID selection, troubleshooting |
references/screenshot-review.md |
Screenshot review — checklist, common problems, fix patterns after capture |
references/powerbi-report-author-cli.md |
CLI metadata — catalog, formatting, expr encode/decode, validate, preview commands |
references/formatting.md |
Core formatting patterns — JSON structure, selectors (precedence rules, dual-entry pattern), VCOs, color routing |
references/formatting-overview.md |
Read first for appearance changes — cascade model, encoding rules, selectors, routing |
references/authoring.md |
Authoring workflows — add pages, add visuals, layout templates, theme registration, drillthrough, interactions |
references/card.md |
Card visual (cardVisual) — single/multi-value templates, instance selectors, accent bar, font scaling |
references/cartesian.md |
Bar/column/line/area/scatter charts — query roles, combo charts, lineStyles, markers, drill hierarchies |
references/table.md |
Table/matrix visuals (pivotTable) — row banding, style presets, column formatting, subtotals |
references/slicers.md |
Slicer visual authoring — 9 slicer types, sizing formulas, fill variant, selection config, mode reference |
references/filters.md |
Filter authoring — 8 filter types, TopN rules, relative dates, inverted selection, filter pane layout |
references/color-strategy.md |
Cross-visual measure-color mapping — theme dataColors, defaultColor, per-series metadata selectors |
references/conditional-formatting.md |
Data-driven formatting — 6 types (FillRule gradients, rules, icons, data bars, web URLs, field values) |
references/re-theming.md |
Re-theming workflow — dark mode, polarity changes, 4-step theme swap procedure |
references/page-formatting.md |
Page-level formatting — canvas background, wallpaper (outspace), background images |
references/filter-pane.md |
Filter pane appearance — outspacePane styling, filter card states (Applied/Available) |
references/textbox.md |
Textbox visuals — paragraphs JSON, dynamic text, rich formatting |
references/shape.md |
Shape visuals — dual-entry selector pattern, available shapes, rotation, text caveat |
references/image.md |
Image visuals — 3 source types, ResourcePackageItem registration, plot area backgrounds |
references/map.md |
Map visuals — Azure Map template, geocoding, ArcGIS |
references/theming.md |
Theme JSON authoring — dataColors, textClasses, visualStyles, dark-mode checklist |
references/expressions.md |
Field expressions — Column, Measure, Aggregation patterns, filter definitions, sort specs |
references/version-control.md |
Git workflows for PBIR — branching, reverting, merge strategies |
references/visual-templates.md |
Generating visual.json — complete JSON templates per visual type, field expression patterns |
references/custom-visuals.md |
Custom visual identifiers, JSON templates, and query roles |
references/formatting-patterns.md |
Advanced formatting: rounded corners, shadows, conditional colors, axis/legend/filter/sort patterns, TOP N filter, drillthrough config, conditional formatting rules (color scales, gradient fills) |
references/common-patterns.md |
Reusable components: KPI rows, slicer panels, background shapes, page navigator, visual interactions, TOP N chart, sync slicers (reportExtensions), page-level filters |
references/bookmark-patterns.md |
Bookmark JSON: toggle visibility, slicer state capture, reset filters, bookmark groups, button→bookmark binding |
references/mobile-layout.md |
Mobile phone layout rules and mobile.json template |
references/required-properties.md |
Required/optional properties per file, theme selection, conditional formatting, format strings |
references/report-template.json |
JSON template for report.json |
references/page-template.json |
JSON template for page.json |
references/pages-metadata-template.json |
JSON template for pages.json |
references/version-template.json |
JSON template for version.json |
references/definition-pbir-template.json |
JSON template for definition.pbir |
references/themes/*.json |
Ready-to-use custom theme files (8 industries) — copy to StaticResources/RegisteredResources/ |
scripts/validate_report.py |
Run after generation — validates cross-references, bookmarks, naming conventions |
scripts/finalize_pbir.py |
Phase 4c polish — snap_grid, align_kpi_row, apply_theme_tokens, normalize_fonts, ensure_alt_text |
scripts/design_quality_check.py |
Phase 4c lint — 14 checks (E1-E4 critical, W1-W10 warnings). Use --style executive|analytical|operational |
scripts/pbir_gate.py |
Unified Phase 4c gate — chains finalize → lint → validate → CLI validate into one pass/fail command |
scripts/pbir_utils.py |
Internal shared helper (constants, logging, console fix) — imported by the 4 scripts above, not run directly |
Quick Reference: Folder Structure
<ReportName>.Report/
├── definition/
│ ├── report.json ← Report settings, theme, custom visuals
│ ├── pages/
│ │ ├── <page-name>/
│ │ │ ├── page.json ← Page config (name, size, type, filters)
│ │ │ └── visuals/
│ │ │ ├── <visual-name>/
│ │ │ │ ├── visual.json ← Visual type, query, formatting
│ │ │ │ └── mobile.json ← Mobile layout overrides (optional)
│ │ │ └── ...
│ │ ├── pages.json ← Page ordering metadata
│ │ └── ...
│ ├── version.json ← Schema version metadata
│ ├── bookmarks/ ← Bookmark definitions (optional)
│ │ ├── bookmarks.json ← Bookmark ordering
│ │ └── <name>.bookmark.json ← Individual bookmark state
│ └── reportExtensions.json ← Report-level extensions (optional)
├── definition.pbir ← Dataset binding reference
├── StaticResources/
│ └── RegisteredResources/ ← Images, custom themes, icons
└── CustomVisuals/ ← Embedded custom visual packages (optional)
Naming Convention
Rules
- Use lowercase-kebab-case for all folder and file names (page folders, visual folders)
- Prefix visual folder names with
visualType for scanability
- Keep names short but descriptive:
card-kpi-revenue, lineChart-monthly-trend
Page Naming
overview # Landing/summary page
sales-analysis # Domain + "analysis"
product-detail # Entity + "detail" (drillthrough)
customer-tooltip # Entity + "tooltip" (tooltip page)
Visual Naming
card-kpi-revenue # card + "kpi" + metric
clusteredBarChart-top-10 # visualType + description
lineChart-monthly-trend # visualType + time grain + metric
slicer-date-range # slicer + field description
shape-header-bg # shape + purpose
textbox-page-title # textbox + purpose
actionButton-back # actionButton + action
pivotTable-sales-by-region # pivotTable + dimension breakdown
Bookmark Naming
tab-sales # tab-{section} for tab navigation
tab-profit
reset-all-filters # reset-{scope} for reset bookmarks
Workflow
Step 0: CLI Setup & Desktop Context
Prerequisite: Node.js 20+. Check with node --version.
Install both CLIs globally:
npm install -g @microsoft/powerbi-report-authoring-cli @microsoft/powerbi-desktop-bridge-cli
Confirm availability:
powerbi-report-author --version
powerbi-desktop --version
Before authoring, understand the model (TMDL files or Semantic Model MCP) and
check Desktop status:
powerbi-desktop status
Step 1: Generate Report-Level Files
These files define the report container. Create them first because page and visual files
reference the theme and settings established here.
definition.pbir — dataset reference
report.json — theme, settings, custom visuals registration
pages.json — page ordering
version.json — schema version
Use JSON templates from references/report-template.json, references/pages-metadata-template.json,
references/version-template.json, references/definition-pbir-template.json.
See references/required-properties.md for property details and theme selection guidance.
Step 2: Generate Pages and Visuals
For each page:
- Create
page.json from references/page-template.json
- For each visual, create
visual.json — use powerbi-report-author catalog describe <type>
for exact roles, then read references/visual-templates.md for JSON templates
- Apply formatting — use
powerbi-report-author formatting list-objects <type> for valid objects,
then read references/formatting-overview.md and references/formatting-patterns.md
- Set up visual interactions in
page.json — see references/common-patterns.md
Step 3: Generate Supporting Files
As needed:
- Bookmarks: Create
bookmarks/bookmarks.json + individual .bookmark.json files
— see references/bookmark-patterns.md and ../power-bi-report-design/references/navigation-patterns.md
- Mobile: Add
mobile.json alongside visual.json — see references/mobile-layout.md
- Custom themes: Place theme JSON in
StaticResources/RegisteredResources/
- Images: Place logos, icons in
StaticResources/RegisteredResources/
- Report extensions:
reportExtensions.json for report-level measures
Step 4: Validate
Power BI Desktop rejects files with JSON syntax errors silently or with cryptic messages.
Always validate before telling the user the report is ready.
Run CLI validation after every logical batch of PBIR edits:
powerbi-report-author validate "<path-to-.Report-dir>"
- Fix every error before Desktop reload.
- Review warnings — unknown visual types usually mean a typo.
- Diagnostics include file paths and JSON paths for direct navigation.
If invoked from the power-bi-developer agent (Phase 4c), use the unified gate:
# Recommended — single command, one pass/fail verdict
python skills/power-bi-report-authoring/scripts/pbir_gate.py `
--report <path-to-.Report-folder> `
--style <style-from-design-spec>
The gate chains 4 stages: finalize_pbir.py → design_quality_check.py → validate_report.py → powerbi-report-author validate (CLI).
Exit codes: 0 = pass, 1 = input error, 2 = fail, 3 = tool error.
Add --allow-warnings to pass with warnings, --json verdict.json to save the result.
Flags: --skip-finalize, --skip-lint, --skip-validate, --skip-schemas.
See ../power-bi-report-design/references/polisher.md for the full Phase 4c routing table.
# 1. Mechanical polish (snap grid, align KPIs, tokenize theme colors, unify fonts, alt text)
# 3. Structural validation (cross-refs, naming, advisories — not schema)
python skills/power-bi-report-authoring/scripts/validate_report.py <path-to-.Report-folder>
# 4. CLI Schema validation
npx powerbi-report-author validate <path-to-.Report-folder>
Per-script exit codes: 0 = pass, 1 = warnings only, 2 = errors present (must fix).
Standalone usage:
python skills/power-bi-report-authoring/scripts/validate_report.py <path-to-.Report-folder>
npx powerbi-report-author validate <path-to-.Report-folder>
validate_report.py checks (schema validation is intentionally NOT duplicated here —
that is the CLI's job):
- JSON syntax — every
.json and .pbir file parses cleanly (needed to run the checks below)
- Cross-references — page folders match
pages.json, bookmarks reference real pages,
custom visuals registered in report.json
- Naming conventions — kebab-case for page and visual folders
- Query semantics — visual query
From items reference a valid Entity/Name
- Drillthrough/tooltip advisories — missing drillthrough filters, oversized tooltip pages
powerbi-report-author validate checks: every file against its correct Microsoft JSON schema
(required properties, $schema, position shape, displayOption enum values, visual vs
visualGroup presence, etc.) — always run this as the source of truth for schema correctness.
Fix all errors before delivering. Warnings are advisory (naming, unused registrations).
If the CLI is not available, validate_report.py alone is not a substitute for schema
validation — install the CLI (Step 0) before delivering a report.
JSON Schema Reference
Schema validation is handled by the powerbi-report-author validate CLI command.
Browse available versions at the GitHub json-schemas repository.
Required Properties (Quick Reference)
Each JSON file must have a $schema property. For full property details, theme selection,
conditional formatting, and format strings, read references/required-properties.md.
| File |
Key Required Properties |
report.json |
themeCollection (with baseTheme.name, reportVersionAtImport, type) |
page.json |
name, displayName, displayOption |
visual.json |
name, position (x, y, height, width), plus visual or visualGroup |
definition.pbir |
version, datasetReference (byPath or byConnection) |
Custom Visuals
When a visual uses a custom visual, you must:
- State the marketplace name and explain why it was chosen over built-in —
custom visuals add rendering overhead and dependency risk, so the benefit must be clear
- Register the
visualType identifier in report.json → publicCustomVisuals array
- Use correct query roles — custom visuals have unique role names (not standard
Category/Y)
Prefer built-in visuals when they can achieve the visualization. Custom visuals shine when
built-in alternatives lack the chart type entirely (e.g., no built-in histogram, Sankey, or
calendar heatmap). Read references/custom-visuals.md for all identifiers, templates, and query roles.
Visual Type Reference
Read ../power-bi-report-design/references/chart-selection-guide.md for WHICH chart to use.
Read references/visual-templates.md for complete JSON templates per visual type.
Read references/custom-visuals.md for custom visual identifiers, templates, and query roles.
Non-data visuals (no query): shape, basicShape, textbox, actionButton, image, pageNavigator.
Field Expressions
Three patterns for binding data to visuals: Column (dimension), Measure (DAX measure),
Aggregation (inline Sum/Avg/Count on a column). Each uses SourceRef.Entity + Property.
See references/visual-templates.md → "Field Expression Patterns" for the full JSON templates.
Aggregation Function codes: 0=Sum, 1=Avg, 2=Count, 3=Min, 4=Max, 5=CountNonNull.
Formatting Patterns
All property values in PBIR use { "expr": { "Literal": { "Value": "<value>" } } } format.
Literal suffixes: D (double), L (long/integer), single-quoted strings, bare booleans.
For advanced formatting (rounded corners, shadows, conditional colors, axis/legend/sort,
theme visual styles, conditional formatting in tables, format strings),
read references/formatting-patterns.md and references/required-properties.md.
Page Types
| Type |
page.json config |
Typical Size |
| Normal page |
(default — no special type) |
1664×936 (standard) |
| Drillthrough |
"type": "Drillthrough" + drillthrough filter fields in filterConfig |
Standard canvas |
| Tooltip |
"type": "Tooltip", "visibility": "HiddenInViewMode" |
Tooltip canvas preset (small) |
| Hidden page |
"visibility": "HiddenInViewMode" |
Standard canvas |
For drillthrough and tooltip page setup details, read references/common-patterns.md.
Bookmarks
Stored in definition/bookmarks/ — bookmarks.json (metadata) + <name>.bookmark.json (state).
Captures: page, filters, slicers, visibility, sort, drill state. Scopes: Data, Display,
Current page, All vs Selected visuals. Use for tab navigation, toggle views, reset filters.
See references/bookmark-patterns.md for complete bookmark JSON patterns
and ../power-bi-report-design/references/navigation-patterns.md for navigation design patterns.
Related Skills
| Skill |
Relationship |
When |
power-bi-report-design |
Upstream (Phase 4a) |
Design Spec drives all JSON generation decisions |
power-bi-semantic-model |
Upstream (Phase 2) |
Model schema needed for queryState column/measure bindings |
power-bi-dax-development |
Upstream (Phase 3) |
Measure names and tables needed for visual data bindings |
power-bi-performance-troubleshooting |
Cross-cutting |
Report-level perf (visual count, slicer cardinality, query reduction) |
power-bi-feedback-iteration |
Downstream (Phase 5) |
Visual formatting fixes and JSON corrections route here |
Edit → Validate → Reload → Screenshot Loop
For rendered-output changes, follow this loop. Do not report completion until
validation, reload, and screenshot review are clean.
┌──────────────────────────────────────────────────────────┐
│ 1. Edit PBIR files │
│ 2. Validate → errors? fix and go to 1 │
│ 3. Desktop status → choose the correct bridge PID │
│ 4. Desktop reload → error? fix PBIR and go to 1 │
│ 5. Screenshot/review → issues? fix and go to 1 │
│ 6. Clean → report completion │
└──────────────────────────────────────────────────────────┘
Rules:
- Step 2 —
powerbi-report-author validate <path-to-.Report-dir>. Pass the
report definition directory (e.g., Sales.Report), not the .pbip file.
- Steps 3–5 — use
powerbi-desktop CLI: status → choose PID → reload --pid <pid>
→ screenshot or screenshot-all → review.
reload covers report/PBIR changes only. For model/TMDL changes, use
semantic-model skill and reopen the PBIP.
- Theme cache: Theme JSON files are cache-keyed by name — Desktop may not
pick up edits on reload. Rename with a random suffix and update
report.json.
- Run reload and screenshot operations serially per PID — never in parallel.
Desktop CLI commands:
| Command |
Purpose |
When |
open "<path.pbip>" |
Launch Desktop for a PBIP |
Starting Desktop |
status |
List instances and bridge state |
Before reload/screenshot |
reload --pid <pid> |
Reload current PBIP report files |
After validated PBIR edits |
screenshot <page-id> --pid <pid> --output <file> |
Capture one page |
Isolated page changes |
screenshot-all --pid <pid> --output-dir <dir> |
Capture every page |
Report-wide changes |
Common outcomes:
| Output/error |
Action |
"not_connected" |
Open report: powerbi-desktop open "<path.pbip>" |
AMBIGUOUS_DESKTOP_INSTANCE |
Run status, choose PID, retry with --pid |
Timeout |
Confirm connected, retry once; persist → --wait-seconds 120 |
Cancelled |
Serialize operations per PID, retry |
ReportDefinitionValidationFailed |
Fix PBIR, validate, reload again |
REPORT_DIR_REQUIRED |
Select correct PID or open target PBIP |
Read references/powerbi-desktop.md for full command reference and troubleshooting.
Read references/screenshot-review.md for the visual review checklist.
Authoring Metadata & Validation CLI
Use powerbi-report-author whenever you need PBIR facts that should not be
guessed: visual types, data roles, formatting objects, property names, enum
values, selectors, expression/value encodings.
| Command |
Purpose |
When |
catalog list |
List built-in visual types |
Choosing visual type |
catalog describe <type> |
Roles, formatting keys, cardinality |
Before creating/editing a visual |
formatting list-objects <type> |
Valid objects.* keys + VCO keys |
Before applying formatting |
formatting describe-object <type> <obj> |
Property names, types, enums; _selectorHint |
Finding exact property names |
formatting search <type> <regex> |
Regex search across all objects |
Don't know which object holds a property |
formatting effective-properties <type> |
Flattened visual objects + VCOs |
Full formatting surface snapshot |
expr encode --kind <t> <v> |
Generate PBIR value encoding |
Writing formatting values |
expr decode '<json>' |
Decode PBIR expression to plain value |
Inspecting existing values |
validate <path> |
Full PBIR validation |
After every batch of changes |
preview-visuals <path> |
Visual inventory across report |
Auditing all visuals |
preview-pages <path> |
Page metadata summary |
Quick page overview |
Read references/powerbi-report-author-cli.md for full command catalog and encoding examples.
Anti-Patterns and Pitfalls
| Pitfall |
Consequence |
Fix |
Using "Entity" inside filter Where conditions |
Filter silently fails |
Use "Source" with the alias from From |
Omitting nativeQueryRef |
Visual calculations may break |
Always include nativeQueryRef |
| Reusing visual/filter names |
Unpredictable behavior |
Generate unique IDs |
Setting visualType to invalid string |
Visual renders as error box |
Run powerbi-report-author catalog describe <type> or powerbi-report-author catalog list |
| Wrong role name for visual type |
Field is ignored; visual blank |
Match role names from powerbi-report-author catalog describe <type> |
Mixing Column and Measure types |
Query fails; visual error |
Columns use Column, measures use Measure |
Forgetting to add page to pages.json |
Page invisible |
Add to pageOrder array |
| Booleans without correct format |
Wrong type |
"true" / "false" (no suffix, unquoted in Value) |
| Numbers without type suffix |
Type mismatch |
D for decimals, L for integers |
Editing $schema version |
PBI Desktop may reject |
Preserve existing version |
Stringified JSON in paragraphs |
Textbox shows nothing |
paragraphs is a native JSON array |
| Using textbox as a thin line/divider |
Renders ~24px tall regardless of height |
Use a shape visual (rectangle) instead — shapes respect small dimensions |
visualContainerObjects as sibling of visual |
Schema validation error in PBI Desktop |
Must be inside visual object, as sibling of objects |
| Partial VCO overrides |
PBI resets omitted properties |
Always set background + border + padding + visualHeader together |
Using tableEx with dimension columns and measures all in Values |
Headers render but no data rows even when DAX confirms data exists |
Use pivotTable; put dimensions in Rows and measures in Values |
Using PowerShell ConvertTo-Json to edit visual JSON |
Property reordering, nesting depth truncation (-Depth default is 2) |
Use Node.js for JSON manipulation, or always pass -Depth 20 and verify structure |
| Using regex or string replacement to modify JSON files |
Corrupts nesting structure — properties end up inside sibling values, braces misalign |
Read file → JSON.parse → modify object → JSON.stringify → write back. Or use the edit tool with exact old/new string matching |
dataPoint.fill without a selector on single-series charts |
Bars/columns invisible despite data in tooltips |
Use dataPoint.defaultColor for a base color without a selector; fill requires a metadata selector |
Using dataPoint.defaultColor on multi-series charts |
All series/categories get the same color — no visual differentiation |
Use theme dataColors for consistent palette across visuals, or dataPoint.fill with metadata selectors for per-series overrides — see color-strategy.md § Color Strategy Quick Reference |
| Clustered bar/column chart colors collapse into one legend color |
The visual has a Series role but all bars and legend markers share the same hue |
Use per-series dataPoint.fill selectors or a theme dataColors palette; do not use defaultColor on clustered charts |
Relying on theme dataColors alone for cross-visual measure consistency |
Same measure gets different colors on different visuals (index-based assignment varies with projection order) |
Maintain a measure→color mapping and apply explicit dataPoint.fill/defaultColor per visual — see color-strategy.md § Cross-Visual Measure-Color Consistency |
Using ThemeDataColor for explicit per-measure dataPoint.fill with metadata selectors |
Colors silently resolve to white or black instead of expected palette color |
Use Literal hex values for explicit color assignments with metadata selectors — ThemeDataColor is unreliable in this context |
| Choosing bar/series colors without checking background contrast |
Bars or lines invisible against page/card background (e.g., white bars on white canvas) |
Always pick saturated, mid-to-dark hues that contrast with the page and VCO background colors |
show property on page-level background |
Schema error — page background only supports color, image, transparency |
Only VCO background (on visuals) has show; page background is always visible |
| Copying property names from doc examples without verifying |
Warnings or silent failures — property names vary by visual type |
Always run powerbi-report-author formatting describe-object <type> <object> for exact property names |
| Guessing which object a property belongs to |
Wasted calls checking wrong objects one by one |
Run powerbi-report-author formatting search <type> <regex> to grep across all objects at once |
| Formatting property has no effect (no error) |
Setting show: false on cardVisual outline without an id selector — validates but renders unchanged |
Check powerbi-report-author formatting describe-object <type> <object> for _selectorHint; use the dual-entry pattern (static + id selector entries) |
Using cardCalloutArea on a single-value card |
Properties validate but have no visible effect — cardCalloutArea only renders on multi-value cards (2+ measures in Data) |
Use outline/accentBar/fillCustom with { id: "default" } selector for single-value cards. For multi-value cards, cardCalloutArea controls per-callout tile styling — see card.md § Multi-Value Formatting |
Using "Fields" as the queryState role for cardVisual |
Cards render empty — PBI Desktop cannot resolve the binding. Validator reports Unknown role "Fields" and Required role "Data" missing |
cardVisual's only data role is "Data". "Fields" is the legacy card visual's role name — never carry it over. Always verify role names with powerbi-report-author catalog describe cardVisual — see card.md § Single-Value Template |
Creating separate single-value cardVisual instances for multiple related KPIs |
Wastes canvas space and misuses the visual type — cardVisual natively supports multiple projections in one tile |
Default to one multi-value cardVisual with all measures as Data projections when ≥2 related KPIs are requested. Only use separate cards when per-card styling differences are required — see card.md § When to Consolidate vs. Keep Separate |
| Adding multiple fields to button slicer Values or Label roles |
Slicer breaks or shows unexpected results — each role accepts only 1 field |
Put one field in Values, one in Label; additional fields go to Tooltips |
Looking at filterConfig on other visuals to understand slicer selections |
Wrong location — selections live only inside the slicer's own visual.json via expansionStates + objects.general.filter |
Always read references/slicers.md first when modifying slicers |
| Creating an image visual without prompting for the source type |
Wrong visual structure — URL vs local file vs data field each have different schemas and expression types |
Always ask the user for the image source (local file / URL / data field) before creating the visual — see image.md § Source Types Overview |
Creating a data-bound image visual with a field that lacks dataCategory: ImageUrl |
Visual renders blank or error |
Warn the user first — present alternatives (other ImageUrl fields, local file, URL) and confirm before creating — see image.md § Select from data |
| Placing background image on page canvas instead of visual plot area |
Background image lands on page.json → objects.background when a visual context was intended |
When a background image is requested in the context of a specific visual, default to plotArea.image. Only use page-level background.image when the user explicitly says "page/canvas background" — see image.md § Plot Area Background Image |
Creating a multiRowCard visual |
Legacy multi-row card — deprecated; powerbi-report-author validate warns with PBIR_VISUAL_TYPE_DEPRECATED |
Always use cardVisual. For multiple KPIs, use a single multi-value cardVisual with all measures as projections in the Data role — see card.md |
Using map or filledMap instead of azureMap for map visuals |
Legacy Bing Maps visuals — deprecated and must not be created; powerbi-report-author validate warns with PBIR_VISUAL_TYPE_DEPRECATED |
Always use azureMap — see map.md. If the map fails to geocode, debug fields or ask the user — do not silently substitute a non-map visual |
Using legacy card/table/matrix |
Deprecated; may break |
Use cardVisual, tableEx, pivotTable |
Creating tableEx/pivotTable without columnAdjustment: growToFit |
Columns shrink-wrap to content, leaving unused whitespace |
Always set columnHeaders.columnAdjustment to growToFit and autoSizeColumnWidth to true — see table.md |
| Custom table/matrix row colors with no effect (white background) |
Default style preset overrides objects-level backColorPrimary/backColorSecondary |
Set stylePreset VCO to 'None' on every tableEx/pivotTable with custom colors — see table.md § Style Presets |
| Table cells white despite dark VCO background |
visualContainerObjects.background only controls outer container — table cells paint on top |
Set dark colors in objects.values.backColorPrimary/Secondary and objects.columnHeaders.backColor, not in VCO — see re-theming.md § Dark Mode Checklist |
| Dark theme applied but cards/tables/slicers still white |
Dark mode triggers every formatting trap simultaneously |
Follow the full re-theming.md § Dark Mode Authoring Checklist — covers stylePreset, fillCustom+id selector, objects vs VCO, and contrast audit |
| Theme JSON changes do not appear after Desktop reload |
Desktop caches theme files by file name |
Rename the theme JSON with a small random suffix, update the theme registration in report.json, then reload; otherwise close and reopen Desktop |
Placing sortDefinition inside visual or at root of visual.json |
Schema validation error; sort silently ignored — chart falls back to alphabetical |
sortDefinition is a property of query — use visual.query.sortDefinition. Supported since visualConfiguration/2.2.0 |
| Container shape fill doesn't match reference |
Text invisible or wrong background color |
Match fill color and transparency to the reference. If the page background already provides the color, skip the shape. If the shape must be invisible, verify text still contrasts with the canvas — see shape.md § Container Shapes |
| Shape text invisible after re-theme |
Shape text object has no explicit fontColor — inherited foreground vanishes against a light fill on a light canvas |
Always set explicit fontColor on shape text objects (in the { selector: { id: "default" } } entry). During re-theming, audit all shapes with text.show: true |
Enabling logAxisScale on data with zero or negative values |
PBI Desktop silently falls back to linear scale — log of zero/negative is undefined |
Warn the user before applying. Present alternatives (filter negatives, switch measure, use labelDisplayUnits). Apply only after all bound values are positive — see cartesian.md § Log Scale |
| Changing theme without sweeping inline overrides |
Old colors remain on shapes, page backgrounds, nav buttons, textboxes — theme-only change has no effect on hardcoded Literal hex at Priority 2 |
Follow re-theming.md § Re-theming Workflow Steps 0–3: build a color mapping, update theme JSON, then bulk-sweep definition/ files for old hex before reload |
Changing only dataColors in theme without sweeping |
Shapes, accent bars, nav button borders retain old accent colors — they use hardcoded Literal hex from the old dataColors array, not ThemeDataColor references |
Sweep ALL old dataColors[N] hex values across definition/ files. Even same-polarity "just change the data colors" requests need the full sweep |
Visual Capability Guardrails
Modern Visual Types (always use)
| Do not create |
Use instead |
card |
cardVisual |
table |
tableEx |
matrix |
pivotTable |
map, filledMap |
azureMap |
Instance Selectors
Some formatting objects need { id: ... } selectors. Run formatting list-objects
and formatting describe-object; follow _selectorHint and the dual-entry pattern
in references/formatting-patterns.md.
1---2name: power-bi-report-authoring3description: Create and modify Power BI report files in PBIR/PBIP format using the `powerbi-report-author` and `powerbi-desktop` CLIs. Use when the user wants to: (1) implement an approved report spec or design brief, (2) add or edit pages, visuals, filters, slicers, bookmarks, themes, or formatting, (3) validate PBIR and verify rendering in Power BI Desktop. For open-ended visual design, use `power-bi-report-design` first. For end-to-end requirements and approval workflow, use `powerbi-report-planning` first. Triggers: "edit PBIR", "create Power BI report page", "add visual to PBIP", "format report visual", "validate Power BI report", "reload Desktop screenshot", "implement an approved PBIP report spec", "edit PBIR pages/visuals".4---56# Power BI PBIP Report Authoring78Create and modify Power BI reports in **PBIR (Power BI Enhanced Report)** format — the9file-based report definition used in PBIP projects. This skill produces and edits the10`.Report/` folder with all JSON files that Power BI Desktop and the Power BI service can11open directly. It also handles live Desktop verification via screenshot workflows.1213**Input:** A Design Spec from the `power-bi-report-design` skill (or equivalent user instructions)14specifying pages, visuals, layout positions, theme, and navigation.1516Canvas size: **1664 × 936** (standard Power BI canvas). Tooltip pages: **320 × 240**.1718## Must/Prefer/Avoid1920### MUST2122- Use CLI capability lookup (`powerbi-report-author catalog/formatting`) before writing23 visual roles, formatting objects, enum values, selectors, or expression encodings.24- Validate PBIR with `powerbi-report-author validate` after each logical batch of edits.25- Use `powerbi-desktop` reload/screenshot workflows for rendered-output changes.26- Never guess PBIR JSON from memory when CLI metadata or reference files are available.2728### PREFER2930- Start from an approved Design Spec or `Design Brief:` for greenfield report builds.31- Route visual-design uncertainty to `power-bi-report-design` before writing files.32- Use the Edit → Validate → Reload → Screenshot loop for any visual change.3334### AVOID3536- Do not create legacy visual types (`card`, `table`, `matrix`, `map`, `filledMap`).37- Do not hardcode property names without CLI confirmation.38- Do not skip Desktop verification for visual changes.3940## Reference Files4142| Reference | When to Read |43|---|---|44| `references/folder-structure.md` | Understanding the full PBIR folder layout |45| `references/powerbi-desktop.md` | **Desktop verification** — open, reload, screenshot, PID selection, troubleshooting |46| `references/screenshot-review.md` | **Screenshot review** — checklist, common problems, fix patterns after capture |47| `references/powerbi-report-author-cli.md` | **CLI metadata** — catalog, formatting, expr encode/decode, validate, preview commands |48| `references/formatting.md` | **Core formatting patterns** — JSON structure, selectors (precedence rules, dual-entry pattern), VCOs, color routing |49| `references/formatting-overview.md` | **Read first for appearance changes** — cascade model, encoding rules, selectors, routing |50| `references/authoring.md` | **Authoring workflows** — add pages, add visuals, layout templates, theme registration, drillthrough, interactions |51| `references/card.md` | Card visual (`cardVisual`) — single/multi-value templates, instance selectors, accent bar, font scaling |52| `references/cartesian.md` | Bar/column/line/area/scatter charts — query roles, combo charts, lineStyles, markers, drill hierarchies |53| `references/table.md` | Table/matrix visuals (`pivotTable`) — row banding, style presets, column formatting, subtotals |54| `references/slicers.md` | Slicer visual authoring — 9 slicer types, sizing formulas, fill variant, selection config, mode reference |55| `references/filters.md` | Filter authoring — 8 filter types, TopN rules, relative dates, inverted selection, filter pane layout |56| `references/color-strategy.md` | Cross-visual measure-color mapping — theme dataColors, defaultColor, per-series metadata selectors |57| `references/conditional-formatting.md` | Data-driven formatting — 6 types (FillRule gradients, rules, icons, data bars, web URLs, field values) |58| `references/re-theming.md` | Re-theming workflow — dark mode, polarity changes, 4-step theme swap procedure |59| `references/page-formatting.md` | Page-level formatting — canvas background, wallpaper (outspace), background images |60| `references/filter-pane.md` | Filter pane appearance — outspacePane styling, filter card states (Applied/Available) |61| `references/textbox.md` | Textbox visuals — paragraphs JSON, dynamic text, rich formatting |62| `references/shape.md` | Shape visuals — dual-entry selector pattern, available shapes, rotation, text caveat |63| `references/image.md` | Image visuals — 3 source types, ResourcePackageItem registration, plot area backgrounds |64| `references/map.md` | Map visuals — Azure Map template, geocoding, ArcGIS |65| `references/theming.md` | Theme JSON authoring — dataColors, textClasses, visualStyles, dark-mode checklist |66| `references/expressions.md` | Field expressions — Column, Measure, Aggregation patterns, filter definitions, sort specs |67| `references/version-control.md` | Git workflows for PBIR — branching, reverting, merge strategies |68| `references/visual-templates.md` | Generating `visual.json` — complete JSON templates per visual type, field expression patterns |69| `references/custom-visuals.md` | Custom visual identifiers, JSON templates, and query roles |70| `references/formatting-patterns.md` | Advanced formatting: rounded corners, shadows, conditional colors, axis/legend/filter/sort patterns, TOP N filter, drillthrough config, conditional formatting rules (color scales, gradient fills) |71| `references/common-patterns.md` | Reusable components: KPI rows, slicer panels, background shapes, page navigator, visual interactions, TOP N chart, sync slicers (reportExtensions), page-level filters |72| `references/bookmark-patterns.md` | Bookmark JSON: toggle visibility, slicer state capture, reset filters, bookmark groups, button→bookmark binding |73| `references/mobile-layout.md` | Mobile phone layout rules and `mobile.json` template |74| `references/required-properties.md` | Required/optional properties per file, theme selection, conditional formatting, format strings |75| `references/report-template.json` | JSON template for `report.json` |76| `references/page-template.json` | JSON template for `page.json` |77| `references/pages-metadata-template.json` | JSON template for `pages.json` |78| `references/version-template.json` | JSON template for `version.json` |79| `references/definition-pbir-template.json` | JSON template for `definition.pbir` |80| `references/themes/*.json` | Ready-to-use custom theme files (8 industries) — copy to `StaticResources/RegisteredResources/` |81| `scripts/validate_report.py` | **Run after generation** — validates cross-references, bookmarks, naming conventions |82| `scripts/finalize_pbir.py` | **Phase 4c polish** — snap_grid, align_kpi_row, apply_theme_tokens, normalize_fonts, ensure_alt_text |83| `scripts/design_quality_check.py` | **Phase 4c lint** — 14 checks (E1-E4 critical, W1-W10 warnings). Use `--style executive\|analytical\|operational` |84| `scripts/pbir_gate.py` | **Unified Phase 4c gate** — chains finalize → lint → validate → CLI validate into one pass/fail command |85| `scripts/pbir_utils.py` | Internal shared helper (constants, logging, console fix) — imported by the 4 scripts above, not run directly |8687## Quick Reference: Folder Structure8889```90<ReportName>.Report/91├── definition/92│ ├── report.json ← Report settings, theme, custom visuals93│ ├── pages/94│ │ ├── <page-name>/95│ │ │ ├── page.json ← Page config (name, size, type, filters)96│ │ │ └── visuals/97│ │ │ ├── <visual-name>/98│ │ │ │ ├── visual.json ← Visual type, query, formatting99│ │ │ │ └── mobile.json ← Mobile layout overrides (optional)100│ │ │ └── ...101│ │ ├── pages.json ← Page ordering metadata102│ │ └── ...103│ ├── version.json ← Schema version metadata104│ ├── bookmarks/ ← Bookmark definitions (optional)105│ │ ├── bookmarks.json ← Bookmark ordering106│ │ └── <name>.bookmark.json ← Individual bookmark state107│ └── reportExtensions.json ← Report-level extensions (optional)108├── definition.pbir ← Dataset binding reference109├── StaticResources/110│ └── RegisteredResources/ ← Images, custom themes, icons111└── CustomVisuals/ ← Embedded custom visual packages (optional)112```113114## Naming Convention115116### Rules117- Use **lowercase-kebab-case** for all folder and file names (page folders, visual folders)118- Prefix visual folder names with `visualType` for scanability119- Keep names short but descriptive: `card-kpi-revenue`, `lineChart-monthly-trend`120121### Page Naming122```123overview # Landing/summary page124sales-analysis # Domain + "analysis"125product-detail # Entity + "detail" (drillthrough)126customer-tooltip # Entity + "tooltip" (tooltip page)127```128129### Visual Naming130```131card-kpi-revenue # card + "kpi" + metric132clusteredBarChart-top-10 # visualType + description133lineChart-monthly-trend # visualType + time grain + metric134slicer-date-range # slicer + field description135shape-header-bg # shape + purpose136textbox-page-title # textbox + purpose137actionButton-back # actionButton + action138pivotTable-sales-by-region # pivotTable + dimension breakdown139```140141### Bookmark Naming142```143tab-sales # tab-{section} for tab navigation144tab-profit145reset-all-filters # reset-{scope} for reset bookmarks146```147148## Workflow149150### Step 0: CLI Setup & Desktop Context151152**Prerequisite: Node.js 20+.** Check with `node --version`.153154Install both CLIs globally:155```bash156npm install -g @microsoft/powerbi-report-authoring-cli @microsoft/powerbi-desktop-bridge-cli157```158159Confirm availability:160```bash161powerbi-report-author --version162powerbi-desktop --version163```164165Before authoring, understand the model (TMDL files or Semantic Model MCP) and166check Desktop status:167```bash168powerbi-desktop status169```170171### Step 1: Generate Report-Level Files172173These files define the report container. Create them first because page and visual files174reference the theme and settings established here.1751761. `definition.pbir` — dataset reference1772. `report.json` — theme, settings, custom visuals registration1783. `pages.json` — page ordering1794. `version.json` — schema version180181Use JSON templates from `references/report-template.json`, `references/pages-metadata-template.json`,182`references/version-template.json`, `references/definition-pbir-template.json`.183See `references/required-properties.md` for property details and theme selection guidance.184185### Step 2: Generate Pages and Visuals186187For each page:1881. Create `page.json` from `references/page-template.json`1892. For each visual, create `visual.json` — use `powerbi-report-author catalog describe <type>`190 for exact roles, then read `references/visual-templates.md` for JSON templates1913. Apply formatting — use `powerbi-report-author formatting list-objects <type>` for valid objects,192 then read `references/formatting-overview.md` and `references/formatting-patterns.md`1934. Set up visual interactions in `page.json` — see `references/common-patterns.md`194195### Step 3: Generate Supporting Files196197As needed:198- **Bookmarks**: Create `bookmarks/bookmarks.json` + individual `.bookmark.json` files199 — see `references/bookmark-patterns.md` and `../power-bi-report-design/references/navigation-patterns.md`200- **Mobile**: Add `mobile.json` alongside `visual.json` — see `references/mobile-layout.md`201- **Custom themes**: Place theme JSON in `StaticResources/RegisteredResources/`202- **Images**: Place logos, icons in `StaticResources/RegisteredResources/`203- **Report extensions**: `reportExtensions.json` for report-level measures204205### Step 4: Validate206207Power BI Desktop rejects files with JSON syntax errors silently or with cryptic messages.208**Always validate before telling the user the report is ready.**209210Run CLI validation after every logical batch of PBIR edits:211```bash212powerbi-report-author validate "<path-to-.Report-dir>"213```214215- Fix every **error** before Desktop reload.216- Review **warnings** — unknown visual types usually mean a typo.217- Diagnostics include file paths and JSON paths for direct navigation.218219**If invoked from the `power-bi-developer` agent (Phase 4c), use the unified gate:**220221```powershell222# Recommended — single command, one pass/fail verdict223python skills/power-bi-report-authoring/scripts/pbir_gate.py `224 --report <path-to-.Report-folder> `225 --style <style-from-design-spec>226```227228The gate chains 4 stages: `finalize_pbir.py` → `design_quality_check.py` → `validate_report.py` → `powerbi-report-author validate` (CLI).229Exit codes: `0` = pass, `1` = input error, `2` = fail, `3` = tool error.230Add `--allow-warnings` to pass with warnings, `--json verdict.json` to save the result.231Flags: `--skip-finalize`, `--skip-lint`, `--skip-validate`, `--skip-schemas`.232See `../power-bi-report-design/references/polisher.md` for the full Phase 4c routing table.233234<details><summary>Manual alternative (run each stage separately)</summary>235236```powershell237# 1. Mechanical polish (snap grid, align KPIs, tokenize theme colors, unify fonts, alt text)238# 3. Structural validation (cross-refs, naming, advisories — not schema)239python skills/power-bi-report-authoring/scripts/validate_report.py <path-to-.Report-folder>240241# 4. CLI Schema validation242npx powerbi-report-author validate <path-to-.Report-folder>243```244245Per-script exit codes: `0` = pass, `1` = warnings only, `2` = errors present (must fix).246247</details>248249**Standalone usage:**250```251python skills/power-bi-report-authoring/scripts/validate_report.py <path-to-.Report-folder>252npx powerbi-report-author validate <path-to-.Report-folder>253```254255`validate_report.py` checks (schema validation is intentionally NOT duplicated here —256that is the CLI's job):2571. **JSON syntax** — every `.json` and `.pbir` file parses cleanly (needed to run the checks below)2582. **Cross-references** — page folders match `pages.json`, bookmarks reference real pages,259 custom visuals registered in `report.json`2603. **Naming conventions** — kebab-case for page and visual folders2614. **Query semantics** — visual query `From` items reference a valid `Entity`/`Name`2625. **Drillthrough/tooltip advisories** — missing drillthrough filters, oversized tooltip pages263264`powerbi-report-author validate` checks: every file against its correct Microsoft JSON schema265(required properties, `$schema`, position shape, `displayOption` enum values, `visual` vs266`visualGroup` presence, etc.) — always run this as the source of truth for schema correctness.267268Fix all **errors** before delivering. **Warnings** are advisory (naming, unused registrations).269270If the CLI is not available, `validate_report.py` alone is not a substitute for schema271validation — install the CLI (Step 0) before delivering a report.272273---274275## JSON Schema Reference276277Schema validation is handled by the `powerbi-report-author validate` CLI command.278Browse available versions at the [GitHub json-schemas repository](https://github.com/microsoft/json-schemas/tree/main/fabric/item/report/definition).279280## Required Properties (Quick Reference)281282Each JSON file must have a `$schema` property. For full property details, theme selection,283conditional formatting, and format strings, read `references/required-properties.md`.284285| File | Key Required Properties |286|---|---|287| `report.json` | `themeCollection` (with `baseTheme.name`, `reportVersionAtImport`, `type`) |288| `page.json` | `name`, `displayName`, `displayOption` |289| `visual.json` | `name`, `position` (`x`, `y`, `height`, `width`), plus `visual` or `visualGroup` |290| `definition.pbir` | `version`, `datasetReference` (`byPath` or `byConnection`) |291292## Custom Visuals293294When a visual uses a **custom visual**, you **must**:2952961. **State the marketplace name** and explain why it was chosen over built-in —297 custom visuals add rendering overhead and dependency risk, so the benefit must be clear2982. **Register** the `visualType` identifier in `report.json` → `publicCustomVisuals` array2993. **Use correct query roles** — custom visuals have unique role names (not standard `Category`/`Y`)300301Prefer built-in visuals when they can achieve the visualization. Custom visuals shine when302built-in alternatives lack the chart type entirely (e.g., no built-in histogram, Sankey, or303calendar heatmap). Read `references/custom-visuals.md` for all identifiers, templates, and query roles.304305## Visual Type Reference306307Read `../power-bi-report-design/references/chart-selection-guide.md` for WHICH chart to use.308Read `references/visual-templates.md` for complete JSON templates per visual type.309Read `references/custom-visuals.md` for custom visual identifiers, templates, and query roles.310311Non-data visuals (no query): `shape`, `basicShape`, `textbox`, `actionButton`, `image`, `pageNavigator`.312313### Field Expressions314315Three patterns for binding data to visuals: **Column** (dimension), **Measure** (DAX measure),316**Aggregation** (inline Sum/Avg/Count on a column). Each uses `SourceRef.Entity` + `Property`.317See `references/visual-templates.md` → "Field Expression Patterns" for the full JSON templates.318319Aggregation `Function` codes: `0`=Sum, `1`=Avg, `2`=Count, `3`=Min, `4`=Max, `5`=CountNonNull.320321## Formatting Patterns322323All property values in PBIR use `{ "expr": { "Literal": { "Value": "<value>" } } }` format.324Literal suffixes: `D` (double), `L` (long/integer), single-quoted strings, bare booleans.325326For advanced formatting (rounded corners, shadows, conditional colors, axis/legend/sort,327theme visual styles, conditional formatting in tables, format strings),328read `references/formatting-patterns.md` and `references/required-properties.md`.329330## Page Types331332| Type | `page.json` config | Typical Size |333|---|---|---|334| Normal page | *(default — no special type)* | 1664×936 (standard) |335| Drillthrough | `"type": "Drillthrough"` + drillthrough filter fields in `filterConfig` | Standard canvas |336| Tooltip | `"type": "Tooltip"`, `"visibility": "HiddenInViewMode"` | Tooltip canvas preset (small) |337| Hidden page | `"visibility": "HiddenInViewMode"` | Standard canvas |338339For drillthrough and tooltip page setup details, read `references/common-patterns.md`.340341## Bookmarks342343Stored in `definition/bookmarks/` — `bookmarks.json` (metadata) + `<name>.bookmark.json` (state).344Captures: page, filters, slicers, visibility, sort, drill state. Scopes: **Data**, **Display**,345**Current page**, **All vs Selected visuals**. Use for tab navigation, toggle views, reset filters.346See `references/bookmark-patterns.md` for complete bookmark JSON patterns347and `../power-bi-report-design/references/navigation-patterns.md` for navigation design patterns.348349## Related Skills350351| Skill | Relationship | When |352|---|---|---|353| `power-bi-report-design` | Upstream (Phase 4a) | Design Spec drives all JSON generation decisions |354| `power-bi-semantic-model` | Upstream (Phase 2) | Model schema needed for queryState column/measure bindings |355| `power-bi-dax-development` | Upstream (Phase 3) | Measure names and tables needed for visual data bindings |356| `power-bi-performance-troubleshooting` | Cross-cutting | Report-level perf (visual count, slicer cardinality, query reduction) |357| `power-bi-feedback-iteration` | Downstream (Phase 5) | Visual formatting fixes and JSON corrections route here |358359---360361## Edit → Validate → Reload → Screenshot Loop362363For rendered-output changes, follow this loop. Do not report completion until364validation, reload, and screenshot review are clean.365366```text367┌──────────────────────────────────────────────────────────┐368│ 1. Edit PBIR files │369│ 2. Validate → errors? fix and go to 1 │370│ 3. Desktop status → choose the correct bridge PID │371│ 4. Desktop reload → error? fix PBIR and go to 1 │372│ 5. Screenshot/review → issues? fix and go to 1 │373│ 6. Clean → report completion │374└──────────────────────────────────────────────────────────┘375```376377**Rules:**378- **Step 2** — `powerbi-report-author validate <path-to-.Report-dir>`. Pass the379 report definition directory (e.g., `Sales.Report`), not the `.pbip` file.380- **Steps 3–5** — use `powerbi-desktop` CLI: `status` → choose PID → `reload --pid <pid>`381 → `screenshot` or `screenshot-all` → review.382- `reload` covers report/PBIR changes only. For model/TMDL changes, use383 semantic-model skill and reopen the PBIP.384- **Theme cache:** Theme JSON files are cache-keyed by name — Desktop may not385 pick up edits on reload. Rename with a random suffix and update `report.json`.386- Run reload and screenshot operations **serially** per PID — never in parallel.387388**Desktop CLI commands:**389390| Command | Purpose | When |391|---|---|---|392| `open "<path.pbip>"` | Launch Desktop for a PBIP | Starting Desktop |393| `status` | List instances and bridge state | Before reload/screenshot |394| `reload --pid <pid>` | Reload current PBIP report files | After validated PBIR edits |395| `screenshot <page-id> --pid <pid> --output <file>` | Capture one page | Isolated page changes |396| `screenshot-all --pid <pid> --output-dir <dir>` | Capture every page | Report-wide changes |397398**Common outcomes:**399400| Output/error | Action |401|---|---|402| `"not_connected"` | Open report: `powerbi-desktop open "<path.pbip>"` |403| `AMBIGUOUS_DESKTOP_INSTANCE` | Run `status`, choose PID, retry with `--pid` |404| `Timeout` | Confirm `connected`, retry once; persist → `--wait-seconds 120` |405| `Cancelled` | Serialize operations per PID, retry |406| `ReportDefinitionValidationFailed` | Fix PBIR, validate, reload again |407| `REPORT_DIR_REQUIRED` | Select correct PID or open target PBIP |408409Read `references/powerbi-desktop.md` for full command reference and troubleshooting.410Read `references/screenshot-review.md` for the visual review checklist.411412---413414## Authoring Metadata & Validation CLI415416Use `powerbi-report-author` whenever you need PBIR facts that should not be417guessed: visual types, data roles, formatting objects, property names, enum418values, selectors, expression/value encodings.419420| Command | Purpose | When |421|---|---|---|422| `catalog list` | List built-in visual types | Choosing visual type |423| `catalog describe <type>` | Roles, formatting keys, cardinality | Before creating/editing a visual |424| `formatting list-objects <type>` | Valid `objects.*` keys + VCO keys | Before applying formatting |425| `formatting describe-object <type> <obj>` | Property names, types, enums; `_selectorHint` | Finding exact property names |426| `formatting search <type> <regex>` | Regex search across all objects | **Don't know which object holds a property** |427| `formatting effective-properties <type>` | Flattened visual objects + VCOs | Full formatting surface snapshot |428| `expr encode --kind <t> <v>` | Generate PBIR value encoding | Writing formatting values |429| `expr decode '<json>'` | Decode PBIR expression to plain value | Inspecting existing values |430| `validate <path>` | Full PBIR validation | **After every batch of changes** |431| `preview-visuals <path>` | Visual inventory across report | Auditing all visuals |432| `preview-pages <path>` | Page metadata summary | Quick page overview |433434Read `references/powerbi-report-author-cli.md` for full command catalog and encoding examples.435436---437438## Anti-Patterns and Pitfalls439440| Pitfall | Consequence | Fix |441|---------|-------------|-----|442| Using `"Entity"` inside filter `Where` conditions | Filter silently fails | Use `"Source"` with the alias from `From` |443| Omitting `nativeQueryRef` | Visual calculations may break | Always include `nativeQueryRef` |444| Reusing visual/filter names | Unpredictable behavior | Generate unique IDs |445| Setting `visualType` to invalid string | Visual renders as error box | Run `powerbi-report-author catalog describe <type>` or `powerbi-report-author catalog list` |446| Wrong role name for visual type | Field is ignored; visual blank | Match role names from `powerbi-report-author catalog describe <type>` |447| Mixing `Column` and `Measure` types | Query fails; visual error | Columns use `Column`, measures use `Measure` |448| Forgetting to add page to `pages.json` | Page invisible | Add to `pageOrder` array |449| Booleans without correct format | Wrong type | `"true"` / `"false"` (no suffix, unquoted in Value) |450| Numbers without type suffix | Type mismatch | `D` for decimals, `L` for integers |451| Editing `$schema` version | PBI Desktop may reject | Preserve existing version |452| Stringified JSON in `paragraphs` | Textbox shows nothing | `paragraphs` is a native JSON array |453| Using textbox as a thin line/divider | Renders ~24px tall regardless of `height` | Use a `shape` visual (rectangle) instead — shapes respect small dimensions |454| `visualContainerObjects` as sibling of `visual` | Schema validation error in PBI Desktop | Must be **inside** `visual` object, as sibling of `objects` |455| Partial VCO overrides | PBI resets omitted properties | Always set background + border + padding + visualHeader together |456| Using `tableEx` with dimension columns and measures all in `Values` | Headers render but no data rows even when DAX confirms data exists | Use `pivotTable`; put dimensions in `Rows` and measures in `Values` |457| Using PowerShell `ConvertTo-Json` to edit visual JSON | Property reordering, nesting depth truncation (`-Depth` default is 2) | Use Node.js for JSON manipulation, or always pass `-Depth 20` and verify structure |458| Using regex or string replacement to modify JSON files | Corrupts nesting structure — properties end up inside sibling values, braces misalign | Read file → `JSON.parse` → modify object → `JSON.stringify` → write back. Or use the `edit` tool with exact old/new string matching |459| `dataPoint.fill` without a selector on single-series charts | Bars/columns invisible despite data in tooltips | Use `dataPoint.defaultColor` for a base color without a selector; `fill` requires a `metadata` selector |460| Using `dataPoint.defaultColor` on multi-series charts | All series/categories get the same color — no visual differentiation | Use theme `dataColors` for consistent palette across visuals, or `dataPoint.fill` with `metadata` selectors for per-series overrides — see [color-strategy.md § Color Strategy Quick Reference](references/color-strategy.md#color-strategy-quick-reference) |461| Clustered bar/column chart colors collapse into one legend color | The visual has a Series role but all bars and legend markers share the same hue | Use per-series `dataPoint.fill` selectors or a theme `dataColors` palette; do not use `defaultColor` on clustered charts |462| Relying on theme `dataColors` alone for cross-visual measure consistency | Same measure gets different colors on different visuals (index-based assignment varies with projection order) | Maintain a measure→color mapping and apply explicit `dataPoint.fill`/`defaultColor` per visual — see [color-strategy.md § Cross-Visual Measure-Color Consistency](references/color-strategy.md#pattern-cross-visual-measure-color-consistency) |463| Using `ThemeDataColor` for explicit per-measure `dataPoint.fill` with metadata selectors | Colors silently resolve to white or black instead of expected palette color | Use `Literal` hex values for explicit color assignments with metadata selectors — `ThemeDataColor` is unreliable in this context |464| Choosing bar/series colors without checking background contrast | Bars or lines invisible against page/card background (e.g., white bars on white canvas) | Always pick saturated, mid-to-dark hues that contrast with the page and VCO background colors |465| `show` property on page-level `background` | Schema error — page `background` only supports `color`, `image`, `transparency` | Only VCO `background` (on visuals) has `show`; page background is always visible |466| Copying property names from doc examples without verifying | Warnings or silent failures — property names vary by visual type | Always run `powerbi-report-author formatting describe-object <type> <object>` for exact property names |467| Guessing which object a property belongs to | Wasted calls checking wrong objects one by one | Run `powerbi-report-author formatting search <type> <regex>` to grep across all objects at once |468| Formatting property has no effect (no error) | Setting `show: false` on cardVisual outline without an id selector — validates but renders unchanged | Check `powerbi-report-author formatting describe-object <type> <object>` for `_selectorHint`; use the dual-entry pattern (static + id selector entries) |469| Using `cardCalloutArea` on a single-value card | Properties validate but have no visible effect — `cardCalloutArea` only renders on multi-value cards (2+ measures in Data) | Use `outline`/`accentBar`/`fillCustom` with `{ id: "default" }` selector for single-value cards. For multi-value cards, `cardCalloutArea` controls per-callout tile styling — see [card.md § Multi-Value Formatting](references/card.md#multi-value-formatting) |470| Using `"Fields"` as the `queryState` role for `cardVisual` | Cards render empty — PBI Desktop cannot resolve the binding. Validator reports `Unknown role "Fields"` and `Required role "Data" missing` | `cardVisual`'s only data role is `"Data"`. `"Fields"` is the legacy `card` visual's role name — never carry it over. Always verify role names with `powerbi-report-author catalog describe cardVisual` — see [card.md § Single-Value Template](references/card.md#single-value-template) |471| Creating separate single-value `cardVisual` instances for multiple related KPIs | Wastes canvas space and misuses the visual type — `cardVisual` natively supports multiple projections in one tile | Default to one multi-value `cardVisual` with all measures as `Data` projections when ≥2 related KPIs are requested. Only use separate cards when per-card styling differences are required — see [card.md § When to Consolidate vs. Keep Separate](references/card.md#when-to-consolidate-vs-keep-separate) |472| Adding multiple fields to button slicer Values or Label roles | Slicer breaks or shows unexpected results — each role accepts only 1 field | Put one field in Values, one in Label; additional fields go to Tooltips |473| Looking at `filterConfig` on other visuals to understand slicer selections | Wrong location — selections live **only** inside the slicer's own `visual.json` via `expansionStates` + `objects.general.filter` | Always read `references/slicers.md` first when modifying slicers |474| Creating an image visual without prompting for the source type | Wrong visual structure — URL vs local file vs data field each have different schemas and expression types | Always ask the user for the image source (local file / URL / data field) before creating the visual — see [image.md § Source Types Overview](references/image.md#source-types-overview) |475| Creating a data-bound image visual with a field that lacks `dataCategory: ImageUrl` | Visual renders blank or error | **Warn the user first** — present alternatives (other ImageUrl fields, local file, URL) and confirm before creating — see [image.md § Select from data](references/image.md#3-select-from-data) |476| Placing background image on page canvas instead of visual plot area | Background image lands on `page.json → objects.background` when a visual context was intended | When a background image is requested in the context of a specific visual, default to `plotArea.image`. Only use page-level `background.image` when the user explicitly says "page/canvas background" — see [image.md § Plot Area Background Image](references/image.md#plot-area-background-image-plotareaimage) |477| Creating a `multiRowCard` visual | Legacy multi-row card — deprecated; `powerbi-report-author validate` warns with `PBIR_VISUAL_TYPE_DEPRECATED` | Always use `cardVisual`. For multiple KPIs, use a single multi-value `cardVisual` with all measures as projections in the `Data` role — see [card.md](references/card.md#multi-value-template) |478| Using `map` or `filledMap` instead of `azureMap` for map visuals | Legacy Bing Maps visuals — deprecated and must not be created; `powerbi-report-author validate` warns with `PBIR_VISUAL_TYPE_DEPRECATED` | Always use `azureMap` — see [map.md](references/map.md). If the map fails to geocode, debug fields or ask the user — do **not** silently substitute a non-map visual |479| Using legacy `card`/`table`/`matrix` | Deprecated; may break | Use `cardVisual`, `tableEx`, `pivotTable` |480| Creating `tableEx`/`pivotTable` without `columnAdjustment: growToFit` | Columns shrink-wrap to content, leaving unused whitespace | Always set `columnHeaders.columnAdjustment` to `growToFit` and `autoSizeColumnWidth` to `true` — see [table.md](references/table.md#default-rule--grow-to-fit) |481| Custom table/matrix row colors with no effect (white background) | Default style preset overrides `objects`-level `backColorPrimary`/`backColorSecondary` | Set `stylePreset` VCO to `'None'` on every `tableEx`/`pivotTable` with custom colors — see [table.md § Style Presets](references/table.md#style-presets-for-tables) |482| Table cells white despite dark VCO background | `visualContainerObjects.background` only controls outer container — table cells paint on top | Set dark colors in `objects.values.backColorPrimary/Secondary` and `objects.columnHeaders.backColor`, not in VCO — see [re-theming.md § Dark Mode Checklist](references/re-theming.md#dark-mode-authoring-checklist) |483| Dark theme applied but cards/tables/slicers still white | Dark mode triggers every formatting trap simultaneously | Follow the full [re-theming.md § Dark Mode Authoring Checklist](references/re-theming.md#dark-mode-authoring-checklist) — covers stylePreset, fillCustom+id selector, objects vs VCO, and contrast audit |484| Theme JSON changes do not appear after Desktop reload | Desktop caches theme files by file name | Rename the theme JSON with a small random suffix, update the theme registration in `report.json`, then reload; otherwise close and reopen Desktop |485| Placing `sortDefinition` inside `visual` or at root of `visual.json` | Schema validation error; sort silently ignored — chart falls back to alphabetical | `sortDefinition` is a property of **`query`** — use `visual.query.sortDefinition`. Supported since `visualConfiguration/2.2.0` |486| Container shape fill doesn't match reference | Text invisible or wrong background color | Match fill color and transparency to the reference. If the page background already provides the color, skip the shape. If the shape must be invisible, verify text still contrasts with the canvas — see [shape.md § Container Shapes](references/shape.md#container-shapes) |487| Shape text invisible after re-theme | Shape `text` object has no explicit `fontColor` — inherited foreground vanishes against a light fill on a light canvas | Always set explicit `fontColor` on shape `text` objects (in the `{ selector: { id: "default" } }` entry). During re-theming, audit all shapes with `text.show: true` |488| Enabling `logAxisScale` on data with zero or negative values | PBI Desktop silently falls back to linear scale — log of zero/negative is undefined | **Warn the user before applying.** Present alternatives (filter negatives, switch measure, use `labelDisplayUnits`). Apply only after all bound values are positive — see [cartesian.md § Log Scale](references/cartesian.md#log-scale-logaxisscale) |489| Changing theme without sweeping inline overrides | Old colors remain on shapes, page backgrounds, nav buttons, textboxes — theme-only change has no effect on hardcoded `Literal` hex at Priority 2 | Follow [re-theming.md § Re-theming Workflow](references/re-theming.md#re-theming-an-existing-report) Steps 0–3: build a color mapping, update theme JSON, then bulk-sweep `definition/` files for old hex before reload |490| Changing only `dataColors` in theme without sweeping | Shapes, accent bars, nav button borders retain old accent colors — they use hardcoded Literal hex from the old `dataColors` array, not `ThemeDataColor` references | Sweep ALL old `dataColors[N]` hex values across `definition/` files. Even same-polarity "just change the data colors" requests need the full sweep |491492---493494## Visual Capability Guardrails495496### Modern Visual Types (always use)497498| Do not create | Use instead |499|---|---|500| `card` | `cardVisual` |501| `table` | `tableEx` |502| `matrix` | `pivotTable` |503| `map`, `filledMap` | `azureMap` |504505### Instance Selectors506507Some formatting objects need `{ id: ... }` selectors. Run `formatting list-objects`508and `formatting describe-object`; follow `_selectorHint` and the dual-entry pattern509in `references/formatting-patterns.md`.