Blocked-by: #6154
Filed unassigned while measuring #6154. Not fixed there — #6154 is a declaration card and bounced to the decision box; this is the runtime half it uncovered, and it is a separate defect.
Baseline: objectui main @ ef2a3bd8d.
The two consumers of one field type disagree
location has two consumers inside @object-ui/fields alone:
- edit —
LocationField (packages/fields/src/widgets/LocationField.tsx:14), which reads value.latitude / value.longitude and nothing else, each behind || 0. - display —
LocationCellRenderer (packages/fields/src/index.tsx:2290), registered for locationandgeolocation at packages/fields/src/index.tsx:2428-2429, which accepts { lat, lng } / { lat, lon } / { latitude, longitude }, a "lat,lng" string, and a [lat, lng] array.
Measured by rendering both against the same values (vitest run from the repo root, happy-dom, throwaway probe, not committed):
| stored value | LocationField (edit, readonly branch) | LocationCellRenderer (display) |
|---|
{ latitude: 30.2741, longitude: 120.1551 } | 30.2741, 120.1551 | 30.2741, 120.1551 |
{ lat: 30.2741, lng: 120.1551 } | 0, 0 | 30.2741, 120.1551 |
{ lat: 30.2741, lon: 120.1551 } | 0, 0 | 30.2741, 120.1551 |
"30.2741,120.1551" | empty | 30.2741, 120.1551 |
[30.2741, 120.1551] | 0, 0 | 30.2741, 120.1551 |
null | empty | empty |
{ latitude: 30.2741 } | 30.2741, 0 | raw JSON fallback |
Why 0, 0 is the bad failure mode
0, 0 is not an error state — it is a valid coordinate in the Gulf of Guinea. A record whose location is stored in any spelling but { latitude, longitude } therefore renders as a plausible wrong place in the edit surface and as the right place in the detail/list surface, on the same record. The partial case is worse in the same direction: { latitude } alone reads 30.2741, 0, silently inventing a longitude the record does not carry.
This is not a hypothetical spelling
The repo itself stores type: 'location' values in both spellings:
{ lat, lng } — packages/plugin-detail/src/__tests__/DetailSection.addressDisplay.test.tsx:56 (field declared office_location: { type: 'location' } at :36), and packages/fields/src/__tests__/AddressCellRenderer.test.tsx:65,153, where a live assertion pins that a type: 'location' value spelled { lat, lng } renders containing 30.2741.{ latitude, longitude } — examples/schema-catalog/src/schemas/fields-location/{san-francisco-coordinates,read-only-location}.json, packages/plugin-detail/src/__tests__/InlineFieldInput.composite.test.tsx.
packages/plugin-map/src/ObjectMap.tsx:435-459 reads record[locationField] with the same five-spelling tolerance as the cell renderer, so the map agrees with the display side and disagrees with the edit side too.
What is not ambiguous
The produce side is settled and single-shaped — measured from onChange:
onChange emissions = [{"latitude":30.2741,"longitude":120.1551}, null]
LocationField emits exactly { latitude: number; longitude: number } or null, never an alias spelling.
Repro
import{LocationField,getCellRenderer,resolveCellRendererType}from'@object-ui/fields';constv={lat: 30.2741,lng: 120.1551};// edit surface → "0, 0"{}}readonly/>// display surface → "30.2741, 120.1551"constR=getCellRenderer(resolveCellRendererType({type: 'location'}));Not decided here
Which side moves is the same question #6154 is bounced on, and should be settled with it rather than separately: either the alias spellings are real (and the edit widget must read them, and the type published for #6154 must cover them), or they are not (and the display renderer's tolerance is the thing to retire, per AGENTS.md #0.1 — which would also require re-fixturing the two { lat, lng } test files above). Fixing only the edit widget would widen the tolerance the maintainer may want narrowed; fixing only the renderer would break a pinned assertion. Recording, not choosing.
Refs: #6154 (the declaration card this was measured under).
Generated by Claude Code
Blocked-by: #6154
Filed unassigned while measuring #6154. Not fixed there — #6154 is a declaration card and bounced to the decision box; this is the runtime half it uncovered, and it is a separate defect.
Baseline: objectui
main@ef2a3bd8d.The two consumers of one field type disagree
locationhas two consumers inside@object-ui/fieldsalone:LocationField(packages/fields/src/widgets/LocationField.tsx:14), which readsvalue.latitude/value.longitudeand nothing else, each behind|| 0.LocationCellRenderer(packages/fields/src/index.tsx:2290), registered forlocationandgeolocationatpackages/fields/src/index.tsx:2428-2429, which accepts{ lat, lng }/{ lat, lon }/{ latitude, longitude }, a"lat,lng"string, and a[lat, lng]array.Measured by rendering both against the same values (
vitest runfrom the repo root,happy-dom, throwaway probe, not committed):LocationField(edit, readonly branch)LocationCellRenderer(display){ latitude: 30.2741, longitude: 120.1551 }30.2741, 120.155130.2741, 120.1551{ lat: 30.2741, lng: 120.1551 }0, 030.2741, 120.1551{ lat: 30.2741, lon: 120.1551 }0, 030.2741, 120.1551"30.2741,120.1551"30.2741, 120.1551[30.2741, 120.1551]0, 030.2741, 120.1551null{ latitude: 30.2741 }30.2741, 0Why
0, 0is the bad failure mode0, 0is not an error state — it is a valid coordinate in the Gulf of Guinea. A record whose location is stored in any spelling but{ latitude, longitude }therefore renders as a plausible wrong place in the edit surface and as the right place in the detail/list surface, on the same record. The partial case is worse in the same direction:{ latitude }alone reads30.2741, 0, silently inventing a longitude the record does not carry.This is not a hypothetical spelling
The repo itself stores
type: 'location'values in both spellings:{ lat, lng }—packages/plugin-detail/src/__tests__/DetailSection.addressDisplay.test.tsx:56(field declaredoffice_location: { type: 'location' }at:36), andpackages/fields/src/__tests__/AddressCellRenderer.test.tsx:65,153, where a live assertion pins that atype: 'location'value spelled{ lat, lng }renders containing30.2741.{ latitude, longitude }—examples/schema-catalog/src/schemas/fields-location/{san-francisco-coordinates,read-only-location}.json,packages/plugin-detail/src/__tests__/InlineFieldInput.composite.test.tsx.packages/plugin-map/src/ObjectMap.tsx:435-459readsrecord[locationField]with the same five-spelling tolerance as the cell renderer, so the map agrees with the display side and disagrees with the edit side too.What is not ambiguous
The produce side is settled and single-shaped — measured from
onChange:LocationFieldemits exactly{ latitude: number; longitude: number }ornull, never an alias spelling.Repro
Not decided here
Which side moves is the same question #6154 is bounced on, and should be settled with it rather than separately: either the alias spellings are real (and the edit widget must read them, and the type published for #6154 must cover them), or they are not (and the display renderer's tolerance is the thing to retire, per AGENTS.md #0.1 — which would also require re-fixturing the two
{ lat, lng }test files above). Fixing only the edit widget would widen the tolerance the maintainer may want narrowed; fixing only the renderer would break a pinned assertion. Recording, not choosing.Refs: #6154 (the declaration card this was measured under).
Generated by Claude Code