Area.totalClimbs reads 0 on a large majority of non-USA leaf areas that
demonstrably hold climbs. Because parent values are the sum of their children,
those zeros propagate, and whole regions undercount badly:
| Area |
totalClimbs |
actual |
undercount |
| British Columbia |
1052 |
8711 |
88% |
| Alberta |
51 |
2310 |
98% |
| Ontario |
298 |
2455 |
88% |
| Squamish |
609 |
2104 |
71% |
| Yosemite Valley 🇺🇸 |
1505 |
1505 |
— |
| Red River Gorge 🇺🇸 |
2674 |
2674 |
— |
Measured 2026-08-17 against https://api.openbeta.io/graphql.
Summed the length of climbs across all leaf descendants, crawled via children.
Reproduce
Paste into graphiql-online against
https://api.openbeta.io/graphql:
query MalamuteCheck {
areas(filter: {area_name: {match: "The Malamute", exactMatch: true}}, limit: 5) {
areaName
totalClimbs
children {
areaName
totalClimbs
metadata { leaf }
climbs { uuid }
authorMetadata { createdAt updatedAt }
}
}
}
The Malamute reports totalClimbs: 0. Its 11 leaf children each report 0 and
between them return 61 climbs:
The Cage totalClimbs=0 climbs=2 created=2023-03-17 updated=2024-10-06
Chasing Rainbows totalClimbs=0 climbs=9 created=2023-03-17 updated=2024-10-06
Grub Street totalClimbs=0 climbs=7 created=2023-03-17 updated=2024-10-06
Jacob's Wall totalClimbs=0 climbs=10 created=2023-03-17 updated=2024-10-06
Lower (CLOSED) totalClimbs=0 climbs=6 created=2023-03-17 updated=2024-10-06
Malamute Bouldering totalClimbs=0 climbs=1 created=2023-03-17 updated=2024-10-06
Overly Hanging Out totalClimbs=0 climbs=1 created=2023-03-17 updated=2024-10-06
Quagmire Area totalClimbs=0 climbs=5 created=2023-03-17 updated=2024-10-06
Starr Wall totalClimbs=0 climbs=14 created=2023-03-17 updated=2024-10-06
Stooges Slab totalClimbs=0 climbs=3 created=2023-03-17 updated=2024-10-06
The Terraces totalClimbs=0 climbs=3 created=2023-03-17 updated=2024-10-06
Squamish reports 609. Those 61 climbs are not in it.
What this is not
The resolvers are fine. The rollup arithmetic is exact wherever we checked
it — Squamish reports 609 and its 31 children sum to exactly 609; Grand Wall
Boulders reports 201 and its 18 children sum to exactly 201. Nothing in the read
path is computing a wrong number. It is faithfully summing wrong stored values.
The field never drifts. Across several thousand leaf areas crawled, the
number that were wrong but non-zero was zero. Every leaf either reports its
climb count exactly or reports 0. A counter that goes stale produces
near-misses; one that is only ever exact-or-absent was never written in the first
place.
Where it comes from
authorMetadata.createdAt separates the two populations cleanly:
| Group |
created |
state |
| USA leaves (Yosemite, Index) |
2022 |
all correct |
| Broken leaves (BC, Alberta) |
2023 — 100% of them |
all 0 |
| Any leaf created 2024 or later |
2024–2026 |
all correct, none broken |
Of British Columbia's 1191 broken leaves, every one was created in 2023; none
created in 2024, 2025 or 2026 is broken. Alberta is identical — all 354 zeros
created in 2023. The timestamps are same-day across a batch, which is what makes
this look like an import rather than organic editing.
Two batch operations look implicated:
- 2023-03-17 — created these areas without populating
totalClimbs.
- 2024-10-06 — touched them again (
updatedAt 2024 on 1190 of the 1191
broken BC leaves) without recomputing it.
The second is probably the more useful lead: something already walked every one
of these rows and did not fix the field.
This is not an ongoing fault. Areas written through the current API get a
correct counter, so the affected set is fixed and will not grow.
Suggested fix
A one-off backfill rather than a change to the write path: recompute totalClimbs from the climbs attached to each leaf, then re-roll up. Because no non-zero value observed was ever wrong, should be safe to run wholesale, since no non-zero value we observed disagreed with its climbs.
Impact on clients
A client using totalClimbs to decide whether an area is worth showing will discard most non-USA crags. Filtering totalClimbs > 0 across the Squamish bbox [-123.2, 49.6, -122.9, 49.8] at zoom 13 returns 180 areas, of which 176 hold at least one climb but only 33 report a non-zero count — the filter throws away 143 real crags.
cragsNear makes this worse, because it returns totalClimbs but an empty
climbs array, so there is no fallback. Petrifying Wall comes back from
cragsNear as totalClimbs: 0 while holding 74 climbs.
Full working
Standalone reproductions — four .graphql files needing no toolchain, plus a
stdlib-only crawler that reports the leaf-vs-totalClimbs breakdown for any
subtree and exits non-zero on disagreement:
https://github.com/jacKlinc/openbeta-mcp/tree/958d8d2e825bdd9da02fcf50f8fff82eb0dd1ae7/docs/findings/totalclimbs
./crosscheck.py --area "British Columbia"
Investigated with AI assistance. Every figure above was produced by querying
the live API and is reproducible with the linked files.
Area.totalClimbsreads0on a large majority of non-USA leaf areas thatdemonstrably hold climbs. Because parent values are the sum of their children,
those zeros propagate, and whole regions undercount badly:
totalClimbsMeasured 2026-08-17 against
https://api.openbeta.io/graphql.Summed the length of climbs across all leaf descendants, crawled via children.
Reproduce
Paste into graphiql-online against
https://api.openbeta.io/graphql:The Malamute reports
totalClimbs: 0. Its 11 leaf children each report0andbetween them return 61 climbs:
Squamish reports 609. Those 61 climbs are not in it.
What this is not
The resolvers are fine. The rollup arithmetic is exact wherever we checked
it — Squamish reports 609 and its 31 children sum to exactly 609; Grand Wall
Boulders reports 201 and its 18 children sum to exactly 201. Nothing in the read
path is computing a wrong number. It is faithfully summing wrong stored values.
The field never drifts. Across several thousand leaf areas crawled, the
number that were wrong but non-zero was zero. Every leaf either reports its
climb count exactly or reports
0. A counter that goes stale producesnear-misses; one that is only ever exact-or-absent was never written in the first
place.
Where it comes from
authorMetadata.createdAtseparates the two populations cleanly:0Of British Columbia's 1191 broken leaves, every one was created in 2023; none
created in 2024, 2025 or 2026 is broken. Alberta is identical — all 354 zeros
created in 2023. The timestamps are same-day across a batch, which is what makes
this look like an import rather than organic editing.
Two batch operations look implicated:
totalClimbs.updatedAt2024 on 1190 of the 1191broken BC leaves) without recomputing it.
The second is probably the more useful lead: something already walked every one
of these rows and did not fix the field.
This is not an ongoing fault. Areas written through the current API get a
correct counter, so the affected set is fixed and will not grow.
Suggested fix
A one-off backfill rather than a change to the write path: recompute
totalClimbsfrom the climbs attached to each leaf, then re-roll up. Because no non-zero value observed was ever wrong, should be safe to run wholesale, since no non-zero value we observed disagreed with its climbs.Impact on clients
A client using
totalClimbsto decide whether an area is worth showing will discard most non-USA crags. FilteringtotalClimbs > 0across the Squamish bbox[-123.2, 49.6, -122.9, 49.8]at zoom 13 returns 180 areas, of which 176 hold at least one climb but only 33 report a non-zero count — the filter throws away 143 real crags.cragsNearmakes this worse, because it returnstotalClimbsbut an emptyclimbsarray, so there is no fallback. Petrifying Wall comes back fromcragsNearastotalClimbs: 0while holding 74 climbs.Full working
Standalone reproductions — four
.graphqlfiles needing no toolchain, plus astdlib-only crawler that reports the leaf-vs-
totalClimbsbreakdown for anysubtree and exits non-zero on disagreement:
https://github.com/jacKlinc/openbeta-mcp/tree/958d8d2e825bdd9da02fcf50f8fff82eb0dd1ae7/docs/findings/totalclimbs
Investigated with AI assistance. Every figure above was produced by querying
the live API and is reproducible with the linked files.