Subchapter 2.16
troubleshooting/common-errors.mdMarkdown8 KBView on GitHub
This is a comprehensive catalog of errors you might encounter while learning Medusa development. Errors are organized by category with symptoms, causes, and step-by-step solutions.
Symptom: Build fails or server crashes with module not found error
Cause: Module not registered in medusa-config.ts
Solution:
medusa-config.tsmodules array:
modules: [
{
resolve: "./modules/brand",
options: {},
},
]npm run devSymptom: Error about module naming convention
Cause: Used kebab-case or PascalCase for module name
Solution: Use camelCase in module definition:
// ❌ WRONG
export default Module("brand-module", { ... })
export default Module("BrandModule", { ... })
// ✅ CORRECT
export default Module("brand", { ... })Symptom: TypeScript errors about missing properties
Cause: Medusa hasn’t regenerated types for new module
Solution:
npx medusa db:migratenpm run devnpm run buildSymptom: TypeScript error or runtime warning
Cause: Workflow function declared as async function
Solution:
Remove async keyword from workflow function:
// ❌ WRONG
createWorkflow("name", async function (input) {
// ...
})
// ✅ CORRECT
createWorkflow("name", function (input) {
// ...
})Symptom: Error about await usage
Cause: Using await when calling steps
Solution:
Remove await - steps are called synchronously in workflow definition:
// ❌ WRONG
const result = await createBrandStep(input)
// ✅ CORRECT
const result = createBrandStep(input)Symptom: Invalid data passes through without errors
Cause: Middleware not configured correctly
Solution:
matcher exactly matches route: "/admin/brands"method is uppercase: "POST"src/api/middlewares.tsSymptom: cURL or browser returns 404
Cause: File not in correct location or not named correctly
Solution:
src/api/admin/brands/route.tsexport const POSThttp://localhost:9000/admin/brandsSymptom: npx medusa db:sync-links fails
Cause: Module not registered or server not recognizing module
Solution:
medusa-config.tsnpm run devnpx medusa db:sync-linksSymptom: Error accessing count, take, skip
Cause: Incorrect destructuring (shouldn’t happen, but handle defensively)
Solution: Use default values:
const {
data: brands,
metadata: { count, take, skip } = {},
} = await query.graph({ ... })
res.json({
brands,
count: count || 0,
limit: take || 15,
offset: skip || 0,
})Symptom: Brand objects don’t have products array
Cause: Middleware defaults don’t include products relation
Solution: Add to middleware defaults:
validateAndTransformQuery(GetBrandsSchema, {
defaults: ["id", "name", "products.*"],
isList: true,
})Symptom: Build or runtime error
Cause: pnpm strict dependency resolution
Solution: Find exact version and install:
pnpm list @tanstack/react-query --depth=10 | grep @medusajs/dashboard
pnpm add @tanstack/react-query@5.x.xSymptom: Widget doesn’t appear on page
Causes and Solutions:
Cause 1: Wrong zone name
"product.details"Cause 2: Config not exported
export const config = defineWidgetConfig({ zone: "..." })Cause 3: File not in correct location
src/admin/widgets/[name].tsxCause 4: Dev server not restarted
npm run devCause 5: Component not default exported
export default WidgetComponentSymptom: Can’t see route in navigation
Causes and Solutions:
Cause 1: Config not exported
export const config = defineRouteConfig({
label: "Brands",
icon: TagSolid,
})Cause 2: Wrong file name
page.tsx (not route.tsx or index.tsx)Cause 3: File not in correct location
src/admin/routes/brands/page.tsxCause 4: Dev server not restarted
Symptom: Runtime error about sdk
Cause: SDK not imported or initialized
Solution:
src/admin/lib/sdk.ts:
import Medusa from "@medusajs/js-sdk"
export const sdk = new Medusa({
baseUrl: import.meta.env.VITE_BACKEND_URL || "/",
debug: import.meta.env.DEV,
auth: { type: "session" },
})import { sdk } from "../../lib/sdk"Symptom: Server can’t connect to PostgreSQL
Cause: Database not running or wrong credentials
Solution:
# macOS with Homebrew
brew services list
brew services start postgresql
# Linux with systemd
sudo systemctl status postgresql
sudo systemctl start postgresql.env:
DATABASE_URL=postgres://user:password@localhost:5432/medusa-dbpsql $DATABASE_URL -c "SELECT 1"Symptom: SQL permission error
Cause: Database user doesn’t have required permissions
Solution: Grant permissions to user:
psql postgres -c "ALTER USER your_user CREATEDB;"
psql your_database -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO your_user;"Symptom: Prices displaying incorrectly (e.g., showing $1999 instead of $19.99)
Cause: Using cents/smallest unit instead of actual price value
Solution: Medusa stores prices as-is, NOT in cents or smallest currency unit:
// ❌ WRONG - Using cents
{
"amount": 1999, // This will display as $1999, not $19.99
"currency_code": "usd"
}
// ✅ CORRECT - Using actual price
{
"amount": 19.99, // This displays correctly as $19.99
"currency_code": "usd"
}Examples:
"amount": 10 (not 1000)"amount": 25.50 (not 2550)"amount": 1000 (not 100000)Why this matters: Payment systems like Stripe use cents, but Medusa handles the conversion internally. Always use the actual price value in your requests and data models.
If you encounter an error not listed here:
When asking for help, include:
npx medusa --versionnode --version