gap: the level-crossing rail gate passes every tile, because rail is a Shortbread attribute key #236

Closed
opened 2026-08-30 10:28:59 +00:00 by viberfox-agent · 0 comments
Collaborator

What I did

Measured the second of the layer's three fetch gates over real tiles, the way
docs/notes/prorail-level-crossings.md's own table samples cells: 64 z14 tiles covering
Groningen (8486..8493 × 5316..5323) from tiles.cartopolis.org, testing each
undecoded body with body_mentions_rail's needles, against one bbox query of the
overweg register bucketed back into cells.

What happened

cells 64   gate passes 64   cells that actually hold a crossing 10   wasted requests 54

The gate passes every tile. Not most — all of them, including the note's own railless
control cell:

Veluwe 8453/5400   11,326 bytes   rail=True  tram=False
    b'bicycle\x1a\x07surface\x1a\x04kind\x1a\x04rail\x1a\x04link\x1a\x0eoneway_rever'

0x1a is field 3 of an MVT Layer — the key table. Shortbread's streets layer
declares an attribute called rail, so the four bytes rail are in the key table of
every streets layer ever emitted, whether or not a single feature in the tile is a
railway. body_mentions_rail therefore answers true for every populated tile on Earth.

The layer's module note says the trade is "a street named 'Railroad Avenue', a POI
called 'Tramhalte' or an attribute key nobody here reads all match too … Each of those
costs one request that comes back with no crossings in it". The attribute key is not an
occasional false positive: it is all of them, always.

What a user would expect

Nothing visible — the layer draws correctly and the envelope still keeps the requests
inside the Netherlands. What a maintainer would expect is that the gate the module
opens with ("Three gates before a request is made … Most of the planet is neither Dutch
nor railed, and an empty answer still costs a round trip and ~0.8 KB") does some of that
work. It does none: the envelope and the Furniture toggle are the only two gates there
are, and every Dutch z14 cell the camera visits sends a PDOK request that comes back
empty roughly nine times in ten.

This is the same shape as #212, on a different gate in a different layer.

Why the test does not catch it

vector_tiles::tests::the_rail_probe_reads_a_kind_value_in_an_undecoded_body builds its
negative case with synth::tagged_line_layer("streets", …, ("kind", "residential"), …),
whose key table holds exactly one key: kind. A real Shortbread streets layer's key
table holds bridge, tunnel, rail, link, oneway_reverse, bicycle, surface
and the rest. The synthetic tile is not shaped like a real one on the one dimension the
probe reads, so the test asserts the opposite of what production sees.

Where the seam is

crates/geo/src/vector_tiles.rs::body_mentions_rail and RAIL_HINTS. A byte search
cannot distinguish a key table from a value table, so either the probe has to move after
the parse (which systems::crossings' module note explains it cannot — the fetch decision
is made before the decode, ADR-033) or the gate should be dropped and the note corrected
to say the envelope is what bounds this layer. body_mentions_water, which reads a layer
name rather than an attribute key, is not affected by this and is worth keeping as the
counter-example.

Filed from the QA pass on #216 (#230).

## What I did Measured the second of the layer's three fetch gates over real tiles, the way `docs/notes/prorail-level-crossings.md`'s own table samples cells: 64 z14 tiles covering Groningen (`8486..8493` × `5316..5323`) from `tiles.cartopolis.org`, testing each undecoded body with `body_mentions_rail`'s needles, against one bbox query of the `overweg` register bucketed back into cells. ## What happened ``` cells 64 gate passes 64 cells that actually hold a crossing 10 wasted requests 54 ``` The gate passes **every** tile. Not most — all of them, including the note's own railless control cell: ``` Veluwe 8453/5400 11,326 bytes rail=True tram=False b'bicycle\x1a\x07surface\x1a\x04kind\x1a\x04rail\x1a\x04link\x1a\x0eoneway_rever' ``` `0x1a` is field 3 of an MVT `Layer` — the **key table**. Shortbread's `streets` layer declares an attribute called `rail`, so the four bytes `rail` are in the key table of every `streets` layer ever emitted, whether or not a single feature in the tile is a railway. `body_mentions_rail` therefore answers `true` for every populated tile on Earth. The layer's module note says the trade is "a street **named** 'Railroad Avenue', a POI called 'Tramhalte' or an attribute key nobody here reads all match too … Each of those costs one request that comes back with no crossings in it". The attribute key is not an occasional false positive: it is all of them, always. ## What a user would expect Nothing visible — the layer draws correctly and the envelope still keeps the requests inside the Netherlands. What a *maintainer* would expect is that the gate the module opens with ("Three gates before a request is made … Most of the planet is neither Dutch nor railed, and an empty answer still costs a round trip and ~0.8 KB") does some of that work. It does none: the envelope and the Furniture toggle are the only two gates there are, and every Dutch z14 cell the camera visits sends a PDOK request that comes back empty roughly nine times in ten. This is the same shape as #212, on a different gate in a different layer. ## Why the test does not catch it `vector_tiles::tests::the_rail_probe_reads_a_kind_value_in_an_undecoded_body` builds its negative case with `synth::tagged_line_layer("streets", …, ("kind", "residential"), …)`, whose key table holds exactly one key: `kind`. A real Shortbread `streets` layer's key table holds `bridge`, `tunnel`, `rail`, `link`, `oneway_reverse`, `bicycle`, `surface` and the rest. The synthetic tile is not shaped like a real one on the one dimension the probe reads, so the test asserts the opposite of what production sees. ## Where the seam is `crates/geo/src/vector_tiles.rs::body_mentions_rail` and `RAIL_HINTS`. A byte search cannot distinguish a key table from a value table, so either the probe has to move after the parse (which `systems::crossings`' module note explains it cannot — the fetch decision is made before the decode, ADR-033) or the gate should be dropped and the note corrected to say the envelope is what bounds this layer. `body_mentions_water`, which reads a layer **name** rather than an attribute key, is not affected by this and is worth keeping as the counter-example. <sub>Filed from the QA pass on #216 (#230).</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jeroen/cartopolis#236
No description provided.