Boloop-made explanatory illustration: a valid long decimal rejected by a local parser despite a successful HTTP response.

On October 21, 2026, Boloop’s GA4 overview could display data while the detailed reports were marked unavailable. The obvious suspicion was a failed Google request. A read-only check showed something different: the same set of seven report queries had all returned HTTP 200.

The failure happened after the responses arrived. Our decimal parser allowed at most nine fractional digits and rejected valid metric values returned by Google. The “provider unavailable” state was wrapping a parsing error on our side.

Unavailable is a result category, not yet a cause

The dashboard needs to remain usable when statistics cannot be read, so external source queries have a fallback: when trustworthy data cannot be obtained, display unavailable rather than inventing zeros.

That behavior matters. The difficulty is that network failures, unexpected response structures, and local parsing errors can all reach the same display state. If an investigation stops at the card’s wording, “this card has no usable data” becomes “Google did not respond successfully.”

We first reproduced the unavailable details in the production admin interface, then checked the corresponding queries separately. The overview and details also came from different results. A working overview could not establish that the details had succeeded, and failed details should not turn an existing overview into zeros.

Two real values exposed the boundary

The returned engagement rate and average session duration were:

engagementRate: 0.2857142857142857
averageSessionDuration: 39.193496142857143

Both had more than nine fractional digits. The old validation rejected the strings before conversion, raised Unexpected GA4 engagement rate, and caused the outer layer to mark the entire detail report unavailable.

Google’s Data API carries a metric’s value as a string, with its type described by the metric header. Validating that string makes sense. A decimal-place limit, however, needs a business or API basis; the number of digits the interface intends to display is not an input format constraint. Google MetricValue documentation

Displaying engagement as 28.6% does not mean the provider may return only one, two, or nine decimal places. Display precision belongs in the presentation layer.

Remove the wrong limit and keep the real boundaries

The repair did not become “convert anything to a number first.” In JavaScript, for example, both Number('') and Number(' ') produce zero. Blind conversion can turn missing or dirty data into a plausible metric.

We removed only the limit of nine fractional digits. Inputs still had to match the site’s accepted nonnegative decimal syntax, convert to a finite number, and remain within its numeric bound. Integer metrics kept their separate integer validation. Response size, timeouts, permissions, and aggregate consistency checks also remained.

The shared parser had two callers at that point: engagement rate and average session duration. Both the dashboard and daily email used a shared method for the detail reports, so the repair belonged there rather than in separate display workarounds.

Put the failing values into the actual calling path

The old normal fixture never reached this boundary. For the regression, we put the two original failing values into the existing complete detail fixture and ran a custom-date query through the actual report parser.

That test failed with the old parser and passed with the fix. It checked not only that a regular expression matched, but also that the parsed engagement rate and average duration equaled the expected numbers. This avoided proving a small helper in isolation from its callers.

We also checked the opposite boundary: empty strings, whitespace-only strings, negative values, NaN, Infinity, trailing text, and values above the site’s limit still had to make the source unavailable. Fixing one overstrict condition did not mean relaxing every other check.

The repair’s analytics regression passed 114 tests, covering reports, daily email, permissions, date ranges, and aggregate mismatches.

Verify the interface and the next email separately

After deployment, refreshing the production dashboard restored engagement, average duration, trends, and the detail tables. In one successful query, daily session and page-view sums matched the aggregate of 7 sessions and 15 views, so the result also passed the existing consistency checks.

Another attempt during the investigation was still unavailable. The conclusion therefore stays with the demonstrated parser defect: valid long decimals are no longer incorrectly rejected locally. It does not promise that every upstream request will always succeed. We did not add blind retries or extend timeouts to conceal a parsing issue.

Email and the dashboard share detail-report logic, but a repaired web page does not establish that a new email has arrived. On deployment day, we kept the next normal delivery as the email acceptance point instead of resending a report to test its text or values. The normal October 22 email provided the actual receipt evidence for the details and updated schedule wording.

When a request succeeds but the interface is unavailable, I now trace three boundaries: did HTTP succeed, did the response have the expected structure, and did the application accept a valid value correctly? Finding the first rejection makes it clear whether to retry the network, correct the data, or remove a restriction that never had a sound basis.