---
title: Deploy + verify /api/errors crawler-noise filter
type: task
status: planned
description: >-
  Both arms of the /api/errors non-actionable-client-error predicate (crawler/environmental/empty,
  and the ResizeObserver-loop browser notification) are deployed; what remains is the 2026-09-08
  soak confirming no new signal opens in either suppressed class while genuine regressions still
  surface.
base_uri: user:task/league/deploy-verify-client-error-crawler-filter.md
created_at: '2026-06-30T04:24:38.200Z'
entity_id: d93a3447-01c8-4f92-aea1-3aa473478d05
observations: []
owner_identity_uri: █████████████████████████
priority: Medium
public_read: true
tags:
  - user:tag/league-xo-football.md
updated_at: '2026-09-06T19:41:35.552Z'
visibility_analyzed_at: '2026-11-06T00:17:49.369Z'
---

## Context

Triage of 16 open `league-client` `log_error` signals (#116121-128, #116158-160,
#116286-287, #116361-363) found all were non-actionable bot/scraper/scanner noise
(Googlebot, datacenter scrapers loading the bundle from a raw-IP mirror host,
and message-less endpoint scanners). The remedy is one exported
predicate, `is_non_actionable_client_error`, gating signal emission at the
`/api/errors` choke point, covered by `test/errors.spec.mjs`.

**Both filter arms are now deployed, and only the soak confirmation remains.**

- The crawler/environmental/empty arm shipped as `mistakia/league@5e363572` and
  reached production well before 2026-09-06 — confirmed by
  `git merge-base --is-ancestor 5e363572e 2722d9001` against the then-current
  production HEAD, which retired this task's original "until deployed, production
  keeps emitting the crawler-noise signals" premise.
- The ResizeObserver-loop arm shipped as `mistakia/league@4cc3f1400` and deployed
  2026-09-06 in the `c140c43bb` range (signal #128716). It went into this same
  predicate rather than a parallel filter. The message is a browser runtime
  notification with no application stack — the browser withholds one by design —
  so no report in that class can be triaged to a component. Anchored at the start
  of the message so `ResizeObserver is not defined` stays actionable.

Verified on the host: `api/routes/errors.mjs:83` carries the anchored rule at
`c140c43bb`.

## Plan

- [x] Deploy the API. Both hosts reached `c140c43bb` on 2026-09-06; `git rev-parse` on `league` and the second production host agree, and `dist/build-manifest.json` names the same sha.
- [x] Smoke-check the route still accepts genuine reports. `test/errors.spec.mjs` covers a real-user `TypeError` and a real `SyntaxError` as non-suppressed, and the ResizeObserver arm carries its own negative control; removing the rule turns exactly the two suppression cases red.
- [ ] On or after **2026-09-08**, confirm no new `league-client` `log_error` signal has opened in either suppressed class: the crawler families (ChunkLoadError, "Failed to fetch", "Load failed", Googlebot SyntaxError) and `log_error:league-client:87be0c63fc6f7cea` (ResizeObserver loop). `base signal list --source league-client --status all`. Genuine user regressions with real app frames should still surface — the pair to check it against is `log_error:league-client:a6345b0c58a73028`, a real crash that the predicate must never have suppressed.
- [ ] If real-user signal was over-suppressed (unlikely — every rule is anchored or class-exact), narrow the predicate; if datacenter-IP spoofed-UA scrapers persist past the UA/class filter, consider an IP/ASN-reputation or per-fingerprint sampling layer.

## Key locations

- `repository/active/league/api/routes/errors.mjs` — `is_non_actionable_client_error` + emission guard
- `repository/active/league/test/errors.spec.mjs` — predicate unit tests, including the negative controls
- Commits `mistakia/league@5e363572` (crawler arm), `mistakia/league@4cc3f1400` (ResizeObserver arm)
- Prior art: `mistakia/league@fe1139a1` (client-side ChunkLoadError recovery in `app/core/bugsnag.js`)
