Problem
vitals crashes --days 7 and vitals anr --days 7 fail with a Google Play Developer
Reporting API HTTP 400 on v0.5.17. The tagged source builds a FULL_RANGE timeline,
but the crash-rate and ANR-rate query methods support DAILY and HOURLY.
The same profiles can read tracks and make valid direct Reporting API queries.
This isolates the failure to Vitals query construction rather than authentication
or rate limiting.
Environment
- Windows, PowerShell.
playconsole-cli v0.5.17.
- Commit
aa0b97a.
- Build
2026-09-10T23:45:08Z.
- Reproduced on 8 October 2026.
gpc below is the installed CLI executable.
- Profile and package identifiers are anonymized.
The GitHub latest release still reports v0.5.17. I also checked master, which
retains the same relevant FULL_RANGE implementation as of this report.
Reproduction
Use an existing profile with Reporting API access and an accessible application:
gpc --profile <profile> --package <package> tracks list
gpc --profile <profile> --package <package> vitals crashes --days 7
gpc --profile <profile> --package <package> vitals anr --days 7
The track read succeeds. Both Vitals commands fail with HTTP 400. Google's error
says that the requested metrics, dimensions and aggregation period do not match
an allowed combination. Its listed alternatives use HOURLY or DAILY.
There was also an earlier failure of vitals overview with the same type of
combination error. I did not repeat the overview call during this diagnosis,
because it queries several metric sets and the shared code already explains why
the crash/ANR query fails.
The command help exposes --days, but no aggregation-period override. Changing
the requested date range cannot change the hardcoded FULL_RANGE value.
Source evidence
In the v0.5.17 Vitals implementation:
queryCrashMetrics, line 470,
calls timelineSpec() and requests crashRate, crashRate7dUserWeighted,
crashRate28dUserWeighted and distinctUsers.
queryANRMetrics, line 492,
calls the same helper and requests anrRate, anrRate7dUserWeighted,
anrRate28dUserWeighted, userPerceivedAnrRate and distinctUsers.
timelineSpec, lines 672 and 679,
sets AggregationPeriod: "FULL_RANGE".
Google documents these supported aggregations for both query methods:
DAILY, with America/Los_Angeles as the supported timezone.
HOURLY, with UTC as the supported timezone. The 28-day rolling metrics are not
supported in hourly queries.
References: crash-rate query
and ANR-rate query.
Successful read-only comparison
Direct calls to the same Reporting API, authenticated with the same affected
profiles, succeeded with HTTP 200 when using supported combinations:
| Aggregation |
Timezone |
Dimensions |
Metrics |
| DAILY |
America/Los_Angeles |
versionCode |
userPerceivedCrashRate, distinctUsers |
| DAILY |
America/Los_Angeles |
versionCode |
userPerceivedAnrRate, distinctUsers |
| HOURLY |
UTC |
versionCode |
userPerceivedCrashRate, distinctUsers |
| HOURLY |
UTC |
versionCode |
userPerceivedAnrRate, distinctUsers |
The queries used a version-code equality filter and the metric set's advertised
freshness boundary for the end time. Some returned rows and some returned an empty
result successfully. This also demonstrates that an empty dataset is distinct
from the invalid-combination error.
I then ran an isolated comparison with the exact metric lists used by the CLI,
without dimensions or filters. For each metric set, credentials, metrics, timezone
and the seven-day date window were identical. Only aggregationPeriod changed:
| Metric set |
Aggregation |
HTTP response |
Result |
| crashRateMetricSet |
FULL_RANGE |
400 |
Invalid metrics/dimensions/aggregation combination |
| crashRateMetricSet |
DAILY |
200 |
Seven daily rows, no continuation token |
| anrRateMetricSet |
FULL_RANGE |
400 |
Invalid metrics/dimensions/aggregation combination |
| anrRateMetricSet |
DAILY |
200 |
Seven daily rows, no continuation token |
The matched window was 29 September 2026 inclusive to 6 October exclusive in
America/Los_Angeles, using the reported DAILY freshness boundary. The crash
metrics were crashRate, crashRate7dUserWeighted, crashRate28dUserWeighted and
distinctUsers. The ANR metrics were anrRate, anrRate7dUserWeighted,
anrRate28dUserWeighted, userPerceivedAnrRate and distinctUsers.
This reproduces the failure and demonstrates that changing the aggregation fixes
the request for both exact CLI metric selections. It does not validate the CLI's
multi-row summary logic. No credentials, authorization headers or app identifiers
are included here.
Earlier observations
An earlier vitals overview --days 7 invocation on 6 October returned the same
400 from its crash-rate query. Historical stability checks in our records used
the Play Console UI instead. I have not established a previously working CLI
Vitals version or a date when Google's behavior changed, so this report does not
claim a new regression caused by v0.5.17.
Proposed fix and related result handling
I propose using DAILY for the crash/ANR date-range queries, retaining the
America/Los_Angeles timezone and selecting an end boundary covered by the metric
set's freshness. Any hourly option must use UTC and hourly-compatible metrics.
Because timelineSpec() is shared with other metric sets, its callers should be
checked before changing its aggregation globally.
Changing the aggregation string alone would leave a result-handling problem.
firstRowMetrics, line 713
reads only rows[0]. A daily query returns a time series, so that row cannot be
presented as a summary of an arbitrary multi-day window. The fix should handle
every returned row and pagination, and define whether the CLI returns dated rows
or an explicitly labelled summary.
For a summary, daily rates need the documented user weighting. Rolling 7-day and
28-day metrics must retain their own time semantics rather than being averaged
again or labelled as an arbitrary --days window. Google's rounded
distinctUsers values must not be summed and labelled as unique users across
the whole period, because the same person can appear on multiple days or hours.
There is also a related no-data issue.
optionalMetrics, line 699
converts missing data to an empty map with a warning.
runOverview, line 243
then reads absent keys as numeric zero. Machine-readable output should distinguish
unavailable data from a measured zero, even when the warning appears on stderr.
Suggested regression coverage
- Generated crash/ANR requests use supported aggregation, timezone and metrics.
- Query windows respect freshness and exclusive end boundaries.
- Multiple returned rows, unordered rows and pagination are handled intentionally.
- Rolling metrics and any period summary have explicit, correct time semantics.
- Rounded daily/hourly user counts are not reported as unique multi-day users.
- Empty responses remain unavailable in overview output; actual zero rates remain
measured zeros.
- Existing shared-timeline callers keep valid request combinations.
I would be happy to prepare a PR with the request fix and regression tests if this
approach fits the project. Before implementing it, I would welcome your preference
on preserving the current summary output versus exposing dated metric rows.
Problem
vitals crashes --days 7andvitals anr --days 7fail with a Google Play DeveloperReporting API HTTP 400 on v0.5.17. The tagged source builds a
FULL_RANGEtimeline,but the crash-rate and ANR-rate query methods support
DAILYandHOURLY.The same profiles can read tracks and make valid direct Reporting API queries.
This isolates the failure to Vitals query construction rather than authentication
or rate limiting.
Environment
playconsole-cli v0.5.17.aa0b97a.2026-09-10T23:45:08Z.gpcbelow is the installed CLI executable.The GitHub latest release still reports v0.5.17. I also checked
master, whichretains the same relevant
FULL_RANGEimplementation as of this report.Reproduction
Use an existing profile with Reporting API access and an accessible application:
The track read succeeds. Both Vitals commands fail with HTTP 400. Google's error
says that the requested metrics, dimensions and aggregation period do not match
an allowed combination. Its listed alternatives use
HOURLYorDAILY.There was also an earlier failure of
vitals overviewwith the same type ofcombination error. I did not repeat the overview call during this diagnosis,
because it queries several metric sets and the shared code already explains why
the crash/ANR query fails.
The command help exposes
--days, but no aggregation-period override. Changingthe requested date range cannot change the hardcoded
FULL_RANGEvalue.Source evidence
In the v0.5.17 Vitals implementation:
queryCrashMetrics, line 470,calls
timelineSpec()and requestscrashRate,crashRate7dUserWeighted,crashRate28dUserWeightedanddistinctUsers.queryANRMetrics, line 492,calls the same helper and requests
anrRate,anrRate7dUserWeighted,anrRate28dUserWeighted,userPerceivedAnrRateanddistinctUsers.timelineSpec, lines 672 and 679,sets
AggregationPeriod: "FULL_RANGE".Google documents these supported aggregations for both query methods:
DAILY, withAmerica/Los_Angelesas the supported timezone.HOURLY, with UTC as the supported timezone. The 28-day rolling metrics are notsupported in hourly queries.
References: crash-rate query
and ANR-rate query.
Successful read-only comparison
Direct calls to the same Reporting API, authenticated with the same affected
profiles, succeeded with HTTP 200 when using supported combinations:
The queries used a version-code equality filter and the metric set's advertised
freshness boundary for the end time. Some returned rows and some returned an empty
result successfully. This also demonstrates that an empty dataset is distinct
from the invalid-combination error.
I then ran an isolated comparison with the exact metric lists used by the CLI,
without dimensions or filters. For each metric set, credentials, metrics, timezone
and the seven-day date window were identical. Only
aggregationPeriodchanged:The matched window was 29 September 2026 inclusive to 6 October exclusive in
America/Los_Angeles, using the reported DAILY freshness boundary. The crashmetrics were
crashRate,crashRate7dUserWeighted,crashRate28dUserWeightedanddistinctUsers. The ANR metrics wereanrRate,anrRate7dUserWeighted,anrRate28dUserWeighted,userPerceivedAnrRateanddistinctUsers.This reproduces the failure and demonstrates that changing the aggregation fixes
the request for both exact CLI metric selections. It does not validate the CLI's
multi-row summary logic. No credentials, authorization headers or app identifiers
are included here.
Earlier observations
An earlier
vitals overview --days 7invocation on 6 October returned the same400 from its crash-rate query. Historical stability checks in our records used
the Play Console UI instead. I have not established a previously working CLI
Vitals version or a date when Google's behavior changed, so this report does not
claim a new regression caused by v0.5.17.
Proposed fix and related result handling
I propose using
DAILYfor the crash/ANR date-range queries, retaining theAmerica/Los_Angelestimezone and selecting an end boundary covered by the metricset's freshness. Any hourly option must use UTC and hourly-compatible metrics.
Because
timelineSpec()is shared with other metric sets, its callers should bechecked before changing its aggregation globally.
Changing the aggregation string alone would leave a result-handling problem.
firstRowMetrics, line 713reads only
rows[0]. A daily query returns a time series, so that row cannot bepresented as a summary of an arbitrary multi-day window. The fix should handle
every returned row and pagination, and define whether the CLI returns dated rows
or an explicitly labelled summary.
For a summary, daily rates need the documented user weighting. Rolling 7-day and
28-day metrics must retain their own time semantics rather than being averaged
again or labelled as an arbitrary
--dayswindow. Google's roundeddistinctUsersvalues must not be summed and labelled as unique users acrossthe whole period, because the same person can appear on multiple days or hours.
There is also a related no-data issue.
optionalMetrics, line 699converts missing data to an empty map with a warning.
runOverview, line 243then reads absent keys as numeric zero. Machine-readable output should distinguish
unavailable data from a measured zero, even when the warning appears on stderr.
Suggested regression coverage
measured zeros.
I would be happy to prepare a PR with the request fix and regression tests if this
approach fits the project. Before implementing it, I would welcome your preference
on preserving the current summary output versus exposing dated metric rows.