Automattic/mongoose · error · Error

Invalid geoJSON type for $geoWithin "${geoWithinType}", must

Error message

Invalid geoJSON type for $geoWithin "${geoWithinType}", must be "Polygon" or "MultiPolygon"

What it means

$geoWithin accepts a GeoJSON $geometry only when its type is 'Polygon' or 'MultiPolygon' -- a search boundary must be an area, not a point or line. lib/cast.js checks the type against an allow-list before using the coordinates and throws this Error for anything else (Point, LineString, GeometryCollection, ...).

Source

Thrown at lib/cast.js:273

                  value.$minDistance,
                  context
                );
              }
              if (isMongooseObject(value.$geometry)) {
                value.$geometry = value.$geometry.toObject({
                  transform: false,
                  virtuals: false
                });
              }
              value = value.$geometry.coordinates;
            } else if (geo === '$geoWithin') {
              if (value.$geometry) {
                if (isMongooseObject(value.$geometry)) {
                  value.$geometry = value.$geometry.toObject({ virtuals: false });
                }
                const geoWithinType = value.$geometry.type;
                if (ALLOWED_GEOWITHIN_GEOJSON_TYPES.indexOf(geoWithinType) === -1) {
                  throw new Error('Invalid geoJSON type for $geoWithin "' +
                    geoWithinType + '", must be "Polygon" or "MultiPolygon"');
                }
                value = value.$geometry.coordinates;
              } else {
                value = value.$box || value.$polygon || value.$center ||
                  value.$centerSphere;
                if (isMongooseObject(value)) {
                  value = value.toObject({ virtuals: false });
                }
              }
            }

            _cast(value, numbertype, context);
            continue;
          }
        }

        if (schema.nested[path]) {

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Put the Polygon/MultiPolygon inside $geoWithin.$geometry and keep the Point as the queried field's value
  2. For the inverse direction (point input, polygon field) use { loc: { $geoIntersects: { $geometry: pointGeoJSON } } }
  3. Validate the type against ['Polygon', 'MultiPolygon'] before building the query

Example fix

// before: a Point cannot bound a $geoWithin
Model.find({ loc: { $geoWithin: { $geometry: { type: 'Point', coordinates: [1, 1] } } } });

// after: find points inside a polygon
Model.find({ loc: { $geoWithin: { $geometry: { type: 'Polygon', coordinates: [[[0, 0], [3, 0], [3, 3], [0, 0]]] } } } });
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = ['Polygon', 'MultiPolygon'];
function assertGeoWithinGeometry(clause) {
  const geo = clause && clause.$geoWithin;
  if (geo && geo.$geometry && !ALLOWED.includes(geo.$geometry.type)) {
    throw new TypeError(
      `$geoWithin type must be Polygon or MultiPolygon, got ${geo.$geometry.type}`
    );
  }
}

Type guard

function isAreaGeometry(g) {
  return g != null &&
    (g.type === 'Polygon' || g.type === 'MultiPolygon') &&
    Array.isArray(g.coordinates);
}

Prevention

When it happens

Trigger: Model.find({ loc: { $geoWithin: { $geometry: { type: 'Point', coordinates: [lng, lat] } } } }); a type field driven by a variable that holds the queried document's type instead of the boundary's; boundary data stored as LineString.

Common situations: Inverting a point-in-polygon query (Point placed in $geoWithin, Polygon used as the field value); copying a $near/$geometry example where Point is correct; unvalidated GeoJSON from clients; renaming GeoJSON types during data migrations.

Related errors


AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21). Data as JSON: /api/errors/b79792892b99c994. Report an issue: GitHub.