The asymmetry that points you toward the real cause
When manual refresh succeeds and scheduled refresh fails, the data source and the data model are not the problem. They work — you just demonstrated that by running a manual refresh. The problem is in the difference between how manual and scheduled refreshes execute.
Manual refresh runs interactively under your identity or a credential you explicitly provide at the time of the refresh. Scheduled refresh runs unattended, at a configured time, using stored credentials and a gateway that must be online without any human involvement. Every cause of the scheduled-vs-manual failure pattern lives in one of those three differences: the stored credentials, the gateway, or the timing.
This asymmetry is diagnostic. It eliminates a large class of potential causes immediately and points you toward the three areas that actually differ between the two execution modes. Starting the investigation anywhere else is working against the evidence.
The gateway is offline between scheduled refresh windows
The most commonly cited cause for scheduled refresh failing while manual works is gateway offline status. The on-premises data gateway service (PBIEgwService) has stopped between the time of the last successful manual refresh and the next scheduled refresh window.
This happens because manual refreshes often work around the problem without the engineer realizing it. The engineer refreshes manually, the gateway starts up (because they opened the gateway application or the service auto-recovered), and the manual refresh succeeds. The next night, when the scheduled refresh runs unattended, the service has stopped again.
Verify gateway status in Power BI Service: go to Settings > Manage gateways. If the gateway shows as offline, the service on the gateway machine has stopped. Connect to the gateway machine and check the service status:
Get-Service -Name "PBIEgwService"
If the service is stopped, start it and immediately set the startup type to Automatic with recovery configured:
Restart-Service -Name "PBIEgwService" sc.exe failure PBIEgwService reset= 86400 actions= restart/5000/restart/10000/restart/20000
The service then restarts automatically after crashes rather than staying stopped until someone notices.
Stored credentials expired after a password rotation
Scheduled refresh uses the credentials stored in Power BI Service at the time of dataset configuration. These stored credentials are not automatically updated when a user changes their password in Active Directory or when a service account credential is rotated.
When credentials expire, manual refresh still works because the engineer is prompted to re-enter credentials interactively. Scheduled refresh has no interactive credential prompt — it uses the stored value, which is now invalid, and fails.
The fix is to update stored credentials in Power BI Service: Dataset settings > Data source credentials > Edit credentials > enter the current password. This must be done every time the account password changes.
The sustainable fix is to move to service accounts with non-expiring credentials or to OAuth-based credentials that refresh their tokens automatically. Organizations with 90-day password rotation policies that forget to update Power BI credentials get predictable gateway failures every three months.
ETL timing conflicts and duplicate values
The scheduled refresh runs at a time configured in Power BI Service — in UTC. If the ETL job that loads the upstream data source runs at an overlapping time, the scheduled refresh may run against a partially loaded dataset. A table that has duplicate values in a key column during an ETL write can produce a relationship error in Power BI's import-mode model, causing the refresh to fail.
This failure mode is intermittent and particularly hard to debug because it depends on the exact moment the scheduled refresh overlaps with the ETL. A manual refresh run during the day — when the ETL has finished and the data is clean — succeeds. The nightly scheduled refresh, which runs at 02:00 UTC during the ETL window, fails.
The fix is to align the scheduled refresh time to start after the ETL window completes, with a buffer. If the ETL reliably finishes by 01:45 UTC, schedule the Power BI refresh for 02:15 UTC. This eliminates the race condition.
Also check the Power BI refresh history for the specific error code. A relationship error caused by duplicate keys looks different from a gateway error — the error message will reference the relationship and the columns involved.
Dynamic data sources blocked in scheduled refresh
Power BI Service cannot evaluate Power Query code that constructs a connection string dynamically at query time — for example, building a URL from a parameter or concatenating a server name from a table value. This class of dynamic source works in Power BI Desktop (where queries run locally) but fails in Power BI Service scheduled refresh, which requires static connection strings.
The error message references privacy levels or mentions that the data source cannot be evaluated. It only appears in scheduled refresh, not in manual refresh run from the desktop.
The fix is to refactor the Power Query so the base URL or server name is static, and only the path or parameters vary. The Web.Contents function supports a RelativePath option that allows static base URLs with dynamic path components:
let BaseUrl = "https://api.example.com", Source = Json.Document(Web.Contents(BaseUrl, [RelativePath = "/data/" & MyParameter])) in Source
The base URL must be a literal string that Power BI Service can evaluate as a fixed endpoint. The relative path can be dynamic. This pattern satisfies the Power BI Service requirement while preserving the parameterization needed in the query.
Personal gateway: not suitable for scheduled refresh
The Power BI personal gateway is designed for individual use: it runs on the user's own machine, requires the user to be logged in, and is not intended for shared or unattended scheduled refreshes. Using a personal gateway for production scheduled refresh is a common and reliable source of the scheduled-vs-manual failure pattern.
The failure mechanism: the personal gateway requires an active user session on the machine it is installed on. When the machine goes to sleep, the user logs out, or the screen locks, the gateway stops processing scheduled refresh jobs. The user then wakes the machine, opens the session, runs a manual refresh, and it works — because the gateway is now running.
For any dataset that needs reliable scheduled refresh, use the standard on-premises data gateway (not the personal mode). Install it on a dedicated server or VM that is always on, never sleeps, and has the gateway service configured to start automatically. The personal gateway is explicitly not designed for production use.
Timezone mismatch in scheduled refresh configuration
Power BI Service schedules refreshes in UTC. The time displayed in the UI may appear in a local timezone depending on the browser and account settings, but the underlying schedule is UTC. Engineers who configure a refresh for "08:00" expecting it to run at 08:00 local time may find the refresh runs at 08:00 UTC — which can be several hours off depending on the timezone.
This doesn't cause scheduled refresh to fail — it causes it to run at the wrong time, which in turn causes it to run during an ETL window it was supposed to avoid, or to miss its SLA window by several hours.
Verify the configured refresh time by checking the dataset settings in Power BI Service and confirming whether the displayed time matches UTC or local time. Adjust the schedule to account for the UTC offset for the intended local run time.
MetricSign: refresh_failed and refresh_delayed as paired signals
MetricSign monitors Power BI datasets via the REST API and generates refresh_failed incidents when a scheduled refresh fails, and refresh_delayed incidents when an expected refresh has not started within a configurable window after its scheduled time.
The refresh_delayed signal is particularly relevant for the gateway offline pattern. When the gateway is offline, the scheduled refresh does not just fail — it often does not start at all. Power BI queues the refresh job but cannot deliver it to the offline gateway. The refresh shows as pending or never starts, rather than failing with an error code.
Having a refresh_delayed alert means the problem is visible before users report stale dashboards — even in cases where the failure mode produces no error code to alert on.