Freika/dawarich · warning

[FamilyLayer] Invalid locations data:

Error message

[FamilyLayer] Invalid locations data:

What it means

FamilyLayer.loadMembers requires an array of member-location objects and warns when handed anything else. The coordinates are then used unconditionally (location.longitude, location.latitude), so passing an error object, null, or a wrapped payload would produce garbage features — hence the early guard. The warn prints the offending value, which tells you exactly what shape arrived instead of the expected array.

Source

Thrown at app/javascript/maps_maplibre/layers/family_layer.js:335

   * Remove family member
   */
  removeMember(memberId) {
    const features = this.data?.features || []
    const filtered = features.filter((f) => f.properties.id !== memberId)

    this.update({
      type: "FeatureCollection",
      features: filtered,
    })
  }

  /**
   * Load all family members from API
   * @param {Object} locations - Array of family member locations
   */
  loadMembers(locations) {
    if (!Array.isArray(locations)) {
      console.warn("[FamilyLayer] Invalid locations data:", locations)
      return
    }

    const features = locations.map((location) => ({
      type: "Feature",
      geometry: {
        type: "Point",
        coordinates: [location.longitude, location.latitude],
      },
      properties: {
        id: location.user_id,
        name: location.email || translate("common.unknown"),
        email: location.email,
        color: location.color || this.getMemberColor(location.user_id),
        lastUpdate: Date.now(),
        battery: location.battery,
        batteryStatus: location.battery_status,
        updatedAt: location.updated_at,

View on GitHub (pinned to 97fad417c5)

Solutions

  1. Log/inspect the value passed to loadMembers and unwrap the correct key from the API response (e.g. data.locations or data.family_members) before calling it.
  2. Handle non-200 responses or error envelopes in the fetching code and skip loadMembers entirely when the payload is not the expected array.
  3. If family tracking can legitimately be off, treat null as "clear the layer" instead of feeding it to loadMembers.

Example fix

// before
familyLayer.loadMembers(data)

// after
const locations = Array.isArray(data) ? data : data?.locations
if (Array.isArray(locations)) {
  familyLayer.loadMembers(locations)
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Array.isArray(locations)) return

Type guard

const isMemberLocations = (d) =>
  Array.isArray(d) && d.every((m) => m && "longitude" in m && "latitude" in m)

Prevention

When it happens

Trigger: The family locations API returned an error envelope like { "error": "..." } or null (family tracking disabled, unauthorized, member has no family), or the caller passed response.data / response JSON wrapper instead of the embedded array (e.g. response.locations).

Common situations: Fetching family locations while family tracking is disabled so the endpoint returns an error hash; API version change wrapping the array in an envelope; ActionCable broadcast delivering an object rather than an array; off-by-one unwrap in the fetch layer.

Related errors


AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21). Data as JSON: /api/errors/95bc8bee0bb2515e. Report an issue: GitHub.