medusajs/medusa · error · MedusaError

Missing required property ${prop} for geo zone type ${geoZon

Error message

Missing required property ${prop} for geo zone type ${geoZone.type}

What it means

Each geo zone type requires an escalating set of properties: country needs country_code; province adds province_code; city adds city; zip adds postal_expression. If any required property for the declared type is missing/falsy, this INVALID_DATA error is thrown.

Source

Thrown at packages/modules/fulfillment/src/services/fulfillment-module-service.ts:2169

  ) {
    const requirePropForType = {
      country: ["country_code"],
      province: ["country_code", "province_code"],
      city: ["country_code", "province_code", "city"],
      zip: ["country_code", "province_code", "city", "postal_expression"],
    }

    for (const geoZone of geoZones) {
      if (!requirePropForType[geoZone.type]) {
        throw new MedusaError(
          MedusaError.Types.INVALID_DATA,
          `Invalid geo zone type: ${geoZone.type}`
        )
      }

      for (const prop of requirePropForType[geoZone.type]) {
        if (!geoZone[prop]) {
          throw new MedusaError(
            MedusaError.Types.INVALID_DATA,
            `Missing required property ${prop} for geo zone type ${geoZone.type}`
          )
        }
      }
    }
  }

  protected static normalizeListShippingOptionsForContextParams(
    filters: FulfillmentTypes.FilterableShippingOptionForContextProps,
    config: FindConfig<ShippingOptionDTO> = {}
  ) {
    let {
      fulfillment_set_id,
      fulfillment_set_type,
      address,
      context,
      ...where

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Provide all required props for the type: country→country_code; province→+province_code; city→+city; zip→+postal_expression
  2. Downgrade the type if you only have partial data (e.g. use 'country' when only country_code is known)
  3. Add conditional form validation based on selected type

Example fix

// before
await service.createGeoZones([{ type: 'zip', country_code: 'us', province_code: 'ca' }])
// after
await service.createGeoZones([{ type: 'zip', country_code: 'us', province_code: 'ca', city: 'LA', postal_expression: '90210' }])
Defensive patterns

Strategy: validation

Validate before calling

const REQUIRED: Record<string, string[]> = { country: ['country_code'], province: ['country_code','province_code'], city: ['country_code','province_code','city'], zip: ['country_code','province_code','city','postal_expression'] }
const missing = (REQUIRED[zone.type] ?? []).filter((p) => !zone[p])
if (missing.length) throw new Error(`Missing: ${missing.join(', ')}`)

Type guard

const hasRequiredGeoZoneProps = (z: any): boolean => (REQUIRED[z.type] ?? []).every((p) => !!z[p])

Prevention

When it happens

Trigger: Creating a zone with type 'zip' but only a country_code, or type 'city' without province_code — commonly from partially-filled forms or sparse CSV imports.

Common situations: Assuming only some fields are required; frontend not enforcing conditional required fields per zone type.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27). Data as JSON: /api/errors/1b3385983a313a0f. Report an issue: GitHub.