medusajs/medusa · error · MedusaError
Invalid step input
Error message
Invalid step input
What it means
Defensive branch in maybeUnsetDefaultBillingAddressesStep: the input matched neither the 'remove' nor the 'update' shape the step expects, so it cannot determine which addresses to unflag. In practice unreachable for well-formed workflow input.
Source
Thrown at packages/core/core-flows/src/customer/steps/maybe-unset-default-billing-addresses.ts:92
if (isDefined(data.create)) {
// eslint-disable-next-line @medusajs/step-must-return-step-response
return unsetForCreate(
data.create,
customerModuleService,
"is_default_billing"
)
}
if (isDefined(data.update)) {
// eslint-disable-next-line @medusajs/step-must-return-step-response
return unsetForUpdate(
data.update,
customerModuleService,
"is_default_billing"
)
}
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"Invalid step input"
)
},
async (addressesToSet, { container }) => {
if (!addressesToSet?.length) {
return
}
const customerModuleService = container.resolve<ICustomerModuleService>(
Modules.CUSTOMER
)
await customerModuleService.updateCustomerAddresses(
{ id: addressesToSet },
{ is_default_billing: true }
)
}View on GitHub (pinned to 5e06e544a2)
Solutions
- Check the step input: it must contain either data.remove (customer/address ids) or data.update (address updates touching is_default_billing)
- Use the official workflows (updateCustomer, createCustomer) instead of composing this internal step yourself
- Pin/upgrade @medusajs/core-flows so the step input type matches your call
Example fix
// before
await maybeUnsetDefaultBillingAddressesStep(container).run({
input: { data: {} },
})
// after
await maybeUnsetDefaultBillingAddressesStep(container).run({
input: { data: { update: [{ id: addrId, is_default_billing: true, customer_id }] } },
}) Defensive patterns
Strategy: type-guard
Validate before calling
if (!('remove' in data || 'update' in data) || (!data.remove && !data.update)) throw new Error('Step input must include remove or update') Type guard
const hasRemoveOrUpdate = (d: { remove?: unknown; update?: unknown }) => !!(d?.remove || d?.update) Prevention
- Don't compose internal steps directly; use official customer workflows
- Keep @medusajs/core-flows version aligned with your custom workflows
When it happens
Trigger: Invoking maybeUnsetDefaultBillingAddressesStep directly with an input object that lacks both data.remove and data.update, or has both falsy.
Common situations: Custom workflow code calling the step directly with a hand-built payload; refactors that renamed the input keys (remove/update); type drift after upgrading @medusajs/core-flows.
Related errors
- Invalid step input
- Line item ${item.title} has no unit price
- Could not find all existing links from data
- Email is required to create a customer
- Customer with this email already has an account
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/c0acd990a31d4eac.
Report an issue: GitHub.