docs: added troubleshooting guides + improvements (#11927)

* docs: added troubleshooting guides + improvements

* build fixes
This commit is contained in:
Shahed Nasser
2025-03-21 11:47:03 +02:00
committed by GitHub
parent c4f75ecbb2
commit 4c33586946
35 changed files with 17258 additions and 15864 deletions
@@ -11,6 +11,8 @@ You can customize the admin dashboard by:
- Adding new sections to existing pages using Widgets.
- Adding new pages using UI Routes.
However, you can't customize the admin dashboard's layout, design, or the content of the existing pages (aside from injecting widgets).
---
## Medusa UI Package
@@ -42,12 +42,12 @@ export const GET = async (
) => {
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const { data: myCustoms } = await query.graph({
entity: "my_custom",
fields: ["id", "name"],
const { data: posts } = await query.graph({
entity: "post",
fields: ["id", "title"],
})
res.json({ my_customs: myCustoms })
res.json({ posts })
}
```
@@ -65,7 +65,7 @@ The method returns an object that has a `data` property, which holds an array of
"data": [
{
"id": "123",
"name": "test"
"title": "My Post"
}
]
}
@@ -88,21 +88,33 @@ Retrieve the records of a linked data model by passing in `fields` the data mode
For example:
```ts highlights={[["6"]]}
const { data: myCustoms } = await query.graph({
entity: "my_custom",
const { data: posts } = await query.graph({
entity: "post",
fields: [
"id",
"name",
"title",
"product.*",
],
})
```
<Note title="Tip">
`.*` means that all of data model's properties should be retrieved. You can also retrieve specific properties by replacing the `*` with the property name, for each property.
`.*` means that all of data model's properties should be retrieved. To retrieve a specific property, replace the `*` with the property's name. For example, `product.title`.
For example:
</Note>
```ts
const { data: posts } = await query.graph({
entity: "post",
fields: [
"id",
"title",
"product.id",
"product.title",
],
})
```
In the example above, you retrieve only the `id` and `title` properties of the `product` linked to a `post`.
### Retrieve List Link Records
@@ -111,19 +123,21 @@ If the linked data model has `isList` enabled in the link definition, pass in `f
For example:
```ts highlights={[["6"]]}
const { data: myCustoms } = await query.graph({
entity: "my_custom",
const { data: posts } = await query.graph({
entity: "post",
fields: [
"id",
"name",
"title",
"products.*",
],
})
```
In the example above, you retrieve all products linked to a post.
### Apply Filters and Pagination on Linked Records
Consider you want to apply filters or pagination configurations on the product(s) linked to `my_custom`. To do that, you must query the module link's table instead.
Consider you want to apply filters or pagination configurations on the product(s) linked to `post`. To do that, you must query the module link's table instead.
As mentioned in the [Module Link](../page.mdx) documentation, Medusa creates a table for your module link. So, not only can you retrieve linked records, but you can also retrieve the records in a module link's table.
@@ -133,19 +147,19 @@ For example:
export const queryLinkTableHighlights = [
["1", "", "Import the module link."],
["6", "productBrandLink.entryPoint", "Pass the `entryPoint` property of the link to Query"],
["7", `"product.*"`, "Retrieve the fields of a product record linked to a `MyCustom` record."],
["7", `"brand.*"`, "Retrieve the fields of a `MyCustom` record linked to a product record."]
["6", "ProductPostLink.entryPoint", "Pass the `entryPoint` property of the link to Query"],
["7", `"product.*"`, "Retrieve the fields of a product record linked to a `Post` record."],
["7", `"post.*"`, "Retrieve the fields of a `Post` record linked to a product record."]
]
```ts highlights={queryLinkTableHighlights}
import productCustomLink from "../../../links/product-custom"
import ProductPostLink from "../../../links/product-post"
// ...
const { data: productCustoms } = await query.graph({
entity: productCustomLink.entryPoint,
fields: ["*", "product.*", "my_custom.*"],
entity: ProductPostLink.entryPoint,
fields: ["*", "product.*", "post.*"],
pagination: {
take: 5,
skip: 0,
@@ -158,8 +172,8 @@ In the object passed to the `graph` method:
- You pass the `entryPoint` property of the link definition as the value for `entity`. So, Query will retrieve records from the module link's table.
- You pass three items to the `field` property:
- `*` to retrieve the link table's fields. This is useful if the link table has [custom columns](../custom-columns/page.mdx).
- `product.*` to retrieve the fields of a product record linked to a `MyCustom` record.
- `my_custom.*` to retrieve the fields of a `MyCustom` record linked to a product record.
- `product.*` to retrieve the fields of a product record linked to a `Post` record.
- `post.*` to retrieve the fields of a `Post` record linked to a product record.
You can then apply any [filters](#apply-filters) or [pagination configurations](#apply-pagination).
@@ -169,58 +183,173 @@ The returned `data` is similar to the following:
[{
"id": "123",
"product_id": "prod_123",
"my_custom_id": "123",
"post_id": "123",
"product": {
"id": "prod_123",
// other product fields...
},
"my_custom": {
"post": {
"id": "123",
// other my_custom fields...
// other post fields...
}
}]
```
---
## Apply Filters
```ts highlights={[["6"], ["7"], ["8"], ["9"]]}
const { data: myCustoms } = await query.graph({
entity: "my_custom",
fields: ["id", "name"],
```ts highlights={[["4"], ["5"], ["6"]]}
const { data: posts } = await query.graph({
entity: "post",
fields: ["id", "title"],
filters: {
id: [
"mc_01HWSVWR4D2XVPQ06DQ8X9K7AX",
"mc_01HWSVWK3KYHKQEE6QGS2JC3FX",
],
id: "post_123",
},
})
```
The `query.graph` function accepts a `filters` property. You can use this property to filter retrieved records.
In the example above, you filter the `my_custom` records by multiple IDs.
In the example above, you filter the `post` records by the ID `post_123`.
You can also filter by multiple values of a property. For example:
```ts highlights={[["4"], ["5"], ["6"], ["7"], ["8"], ["9"]]}
const { data: posts } = await query.graph({
entity: "post",
fields: ["id", "title"],
filters: {
id: [
"post_123",
"post_321",
],
},
})
```
In the example above, you filter the `post` records by multiple IDs.
<Note>
Filters don't apply on fields of linked data models from other modules.
Filters don't apply on fields of linked data models from other modules. Refer to the [Retrieve Linked Records](#retrieve-linked-records) section for an alternative solution.
</Note>
### Advanced Query Filters
Under the hood, Query uses the `listX` (`listPosts`) method of the data model's module's service to retrieve records. This method accepts a filter object that can be used to filter records.
Those filters don't just allow you to filter by exact values. You can also filter by properties that don't match a value, match multiple values, and other filter types.
Refer to the [Service Factory Reference](!resources!/service-factory-reference/tips/filtering) for examples of advanced filters. The following sections provide some quick examples.
#### Filter by Not Matching a Value
```ts highlights={[["4"], ["5"], ["6"], ["7"], ["8"]]}
const { data: posts } = await query.graph({
entity: "post",
fields: ["id", "title"],
filters: {
title: {
$ne: null,
},
},
})
```
In the example above, only posts that have a title are retrieved.
#### Filter by Not Matching Multiple Values
```ts highlights={[["4"], ["5"], ["6"], ["7"], ["8"]]}
const { data: posts } = await query.graph({
entity: "post",
fields: ["id", "title"],
filters: {
title: {
$nin: ["My Post", "Another Post"],
},
},
})
```
In the example above, only posts that don't have the title `My Post` or `Another Post` are retrieved.
#### Filter by a Range
```ts highlights={[["10"], ["11"], ["12"], ["13"], ["14"], ["15"]]}
const startToday = new Date()
startToday.setHours(0, 0, 0, 0)
const endToday = new Date()
endToday.setHours(23, 59, 59, 59)
const { data: posts } = await query.graph({
entity: "post",
fields: ["id", "title"],
filters: {
published_at: {
$gt: startToday,
$lt: endToday,
},
},
})
```
In the example above, only posts that were published today are retrieved.
#### Filter Text by Like Value
<Note>
This filter only applies to text-like properties, including `text`, `id`, and `enum` properties.
</Note>
```ts highlights={[["4"], ["5"], ["6"], ["7"], ["8"]]}
const { data: posts } = await query.graph({
entity: "post",
fields: ["id", "title"],
filters: {
title: {
$like: "%My%",
},
},
})
```
In the example above, only posts that have the word `My` in their title are retrieved.
#### Filter a Relation's Property
```ts highlights={[["4"], ["5"], ["6"], ["7"], ["8"]]}
const { data: posts } = await query.graph({
entity: "post",
fields: ["id", "title"],
filters: {
author: {
name: "John",
},
},
})
```
While it's not possible to filter by a linked data model's property, you can filter by a relation's property (that is, the property of a related data model that is defined in the same module).
In the example above, only posts that have an author with the name `John` are retrieved.
---
## Apply Pagination
```ts highlights={[["8", "skip", "The number of records to skip before fetching the results."], ["9", "take", "The number of records to fetch."]]}
const {
data: myCustoms,
data: posts,
metadata: { count, take, skip } = {},
} = await query.graph({
entity: "my_custom",
fields: ["id", "name"],
entity: "post",
fields: ["id", "title"],
pagination: {
skip: 0,
take: 10,
@@ -258,9 +387,9 @@ When you provide the pagination fields, the `query.graph` method's returned obje
### Sort Records
```ts highlights={[["5"], ["6"], ["7"]]}
const { data: myCustoms } = await query.graph({
entity: "my_custom",
fields: ["id", "name"],
const { data: posts } = await query.graph({
entity: "post",
fields: ["id", "title"],
pagination: {
order: {
name: "DESC",
@@ -284,6 +413,72 @@ The `order` property is an object whose keys are property names, and values are
---
## Configure Query to Throw Errors
By default, if Query doesn't find records matching your query, it returns an empty array. You can add option to configure Query to throw an error when no records are found.
The `query.graph` method accepts as a second parameter an object that can have a `throwIfKeyNotFound` property. Its value is a boolean indicating whether to throw an error if no record is found when filtering by IDs. By default, it's `false`.
For example:
```ts
const { data: posts } = await query.graph({
entity: "post",
fields: ["id", "title"],
filters: {
id: "post_123",
},
}, {
throwIfKeyNotFound: true,
})
```
In the example above, if no post is found with the ID `post_123`, Query will throw an error. This is useful to stop execution when a record is expected to exist.
### Throw Error on Related Data Model
The `throwIfKeyNotFound` option can also be used to throw an error if the ID of a related data model's record (in the same module) is passed in the filters, and the related record doesn't exist.
For example:
```ts
const { data: posts } = await query.graph({
entity: "post",
fields: ["id", "title", "author.*"],
filters: {
id: "post_123",
author_id: "author_123",
},
}, {
throwIfKeyNotFound: true,
})
```
In the example above, Query throws an error either if no post is found with the ID `post_123` or if its found but its author ID isn't `author_123`.
In the above example, it's assumed that a post belongs to an author, so it has an `author_id` property. However, this also works in the opposite case, where an author has many posts.
For example:
```ts
const { data: posts } = await query.graph({
entity: "author",
fields: ["id", "name", "posts.*"],
filters: {
id: "author_123",
posts: {
id: "post_123",
},
},
}, {
throwIfKeyNotFound: true,
})
```
In the example above, Query throws an error if no author is found with the ID `author_123` or if the author is found but doesn't have a post with the ID `post_123`.
---
## Request Query Configurations
For API routes that retrieve a single or list of resources, Medusa provides a `validateAndTransformQuery` middleware that:
@@ -317,7 +512,7 @@ export default defineMiddlewares({
{
defaults: [
"id",
"name",
"title",
"products.*",
],
isList: true,
@@ -375,12 +570,12 @@ export const GET = async (
) => {
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const { data: myCustoms } = await query.graph({
entity: "my_custom",
const { data: posts } = await query.graph({
entity: "post",
...req.queryConfig,
})
res.json({ my_customs: myCustoms })
res.json({ posts: posts })
}
```
@@ -394,10 +589,10 @@ To test it out, start your Medusa application and send a `GET` request to the `/
```json title="Returned Data"
{
"my_customs": [
"posts": [
{
"id": "123",
"name": "test"
"title": "test"
}
]
}
@@ -51,7 +51,7 @@ export default defineLink(
},
ProductModule.linkable.product,
{
readOnly: true
readOnly: true,
}
)
```
@@ -76,8 +76,8 @@ const { result } = await query.graph({
entity: "post",
fields: ["id", "product.*"],
filters: {
id: "post_123"
}
id: "post_123",
},
})
```
@@ -114,7 +114,7 @@ export default defineLink(
primaryKey: "product_id",
},
{
readOnly: true
readOnly: true,
}
)
```
@@ -133,8 +133,8 @@ const { result } = await query.graph({
entity: "product",
fields: ["id", "post.*"],
filters: {
id: "prod_123"
}
id: "prod_123",
},
})
```
@@ -194,7 +194,7 @@ export default defineLink(
},
ProductModule.linkable.product,
{
readOnly: true
readOnly: true,
}
)
```
@@ -229,7 +229,7 @@ export default defineLink(
},
ProductModule.linkable.product,
{
readOnly: true
readOnly: true,
}
)
```
@@ -276,7 +276,7 @@ export default defineLink(
primaryKey: "product_id",
},
{
readOnly: true
readOnly: true,
}
)
```
@@ -343,14 +343,14 @@ export default defineLink(
{
linkable: ProductModule.linkable.product,
field: "id",
isList: true
isList: true,
},
{
...BlogModule.linkable.post.id,
primaryKey: "product_id"
primaryKey: "product_id",
},
{
readOnly: true
readOnly: true,
}
)
```
@@ -444,14 +444,14 @@ import { CMS_MODULE } from "../modules/cms"
export default defineLink(
{
linkable: ProductModule.linkable.product,
field: "id"
field: "id",
},
{
linkable: {
serviceName: CMS_MODULE,
alias: "cms_post",
primaryKey: "product_id",
}
},
},
{
readOnly: true,
@@ -28,8 +28,8 @@ So, to run database queries in a service:
For example, in your service, add the following methods:
export const methodsHighlight = [
["12", "getCount", "Retrieves the number of records in `my_custom` using the `count` method."],
["19", "getCountSql", "Retrieves the number of records in `my_custom` using the `execute` method."]
["13", "getCount", "Retrieves the number of records in `my_custom` using the `count` method."],
["20", "getCountSql", "Retrieves the number of records in `my_custom` using the `execute` method."]
]
```ts highlights={methodsHighlight}
@@ -38,7 +38,8 @@ import {
InjectManager,
MedusaContext,
} from "@medusajs/framework/utils"
import { SqlEntityManager } from "@mikro-orm/knex"
import { Context } from "@medusajs/framework/types"
import { EntityManager } from "@mikro-orm/knex"
class BlogModuleService {
// ...
@@ -46,19 +47,19 @@ class BlogModuleService {
@InjectManager()
async getCount(
@MedusaContext() sharedContext?: Context<EntityManager>
): Promise<number> {
return await sharedContext.manager.count("my_custom")
): Promise<number | undefined> {
return await sharedContext?.manager?.count("my_custom")
}
@InjectManager()
async getCountSql(
@MedusaContext() sharedContext?: Context<EntityManager>
): Promise<number> {
const data = await sharedContext.manager.execute(
const data = await sharedContext?.manager?.execute(
"SELECT COUNT(*) as num FROM my_custom"
)
return parseInt(data[0].num)
return parseInt(data?.[0].num || 0)
}
}
```
@@ -115,8 +116,8 @@ class BlogModuleService {
},
@MedusaContext() sharedContext?: Context<EntityManager>
): Promise<any> {
const transactionManager = sharedContext.transactionManager
await transactionManager.nativeUpdate(
const transactionManager = sharedContext?.transactionManager
await transactionManager?.nativeUpdate(
"my_custom",
{
id: input.id,
@@ -127,7 +128,7 @@ class BlogModuleService {
)
// retrieve again
const updatedRecord = await transactionManager.execute(
const updatedRecord = await transactionManager?.execute(
`SELECT * FROM my_custom WHERE id = '${input.id}'`
)
@@ -178,10 +179,22 @@ For example, the `update` method could be changed to the following:
```ts
// other imports...
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
} from "@medusajs/framework/utils"
import { Context } from "@medusajs/framework/types"
import { EntityManager } from "@mikro-orm/knex"
class BlogModuleService {
// ...
@InjectTransactionManager()
protected async update_(
// ...
): Promise<any> {
// ...
}
@InjectManager()
async update(
input: {
@@ -192,12 +205,14 @@ class BlogModuleService {
) {
const newData = await this.update_(input, sharedContext)
await sendNewDataToSystem(newData)
// example method that sends data to another system
await this.sendNewDataToSystem(newData)
return newData
}
}
```
In this case, only the `update_` method is wrapped in a transaction. The returned value `newData` holds the committed result, which can be used for other operations, such as passed to a `sendNewDataToSystem` method.
### Using Methods in Transactional Methods
@@ -208,6 +223,11 @@ For example:
```ts
// other imports...
import {
InjectTransactionManager,
MedusaContext,
} from "@medusajs/framework/utils"
import { Context } from "@medusajs/framework/types"
import { EntityManager } from "@mikro-orm/knex"
class BlogModuleService {
@@ -343,7 +363,7 @@ class BlogModuleService {
return updatedRecord
},
{
transaction: sharedContext.transactionManager,
transaction: sharedContext?.transactionManager,
}
)
}
@@ -382,6 +402,12 @@ The second parameter of the `baseRepository_.transaction` method is an object of
```ts highlights={[["16"]]}
// other imports...
import { EntityManager } from "@mikro-orm/knex"
import {
InjectTransactionManager,
MedusaContext,
} from "@medusajs/framework/utils"
import { Context } from "@medusajs/framework/types"
import { EntityManager } from "@mikro-orm/knex"
class BlogModuleService {
// ...
@@ -398,7 +424,7 @@ class BlogModuleService {
// ...
},
{
transaction: sharedContext.transactionManager,
transaction: sharedContext?.transactionManager,
}
)
}
@@ -414,6 +440,12 @@ class BlogModuleService {
```ts highlights={[["19"]]}
// other imports...
import {
InjectTransactionManager,
MedusaContext,
} from "@medusajs/framework/utils"
import { Context } from "@medusajs/framework/types"
import { EntityManager } from "@mikro-orm/knex"
import { IsolationLevel } from "@mikro-orm/core"
class BlogModuleService {
@@ -442,6 +474,14 @@ class BlogModuleService {
- If `transaction` is provided and this is disabled, the manager in `transaction` is re-used.
```ts highlights={[["16"]]}
// other imports...
import {
InjectTransactionManager,
MedusaContext,
} from "@medusajs/framework/utils"
import { Context } from "@medusajs/framework/types"
import { EntityManager } from "@mikro-orm/knex"
class BlogModuleService {
// ...
@InjectTransactionManager()
+4 -4
View File
@@ -31,7 +31,7 @@ export const generatedEditDates = {
"app/learn/fundamentals/events-and-subscribers/emit-event/page.mdx": "2025-03-18T15:09:40.243Z",
"app/learn/fundamentals/workflows/conditions/page.mdx": "2025-01-27T08:45:19.027Z",
"app/learn/fundamentals/modules/module-link-directions/page.mdx": "2024-07-24T09:16:01+02:00",
"app/learn/fundamentals/admin/page.mdx": "2024-10-23T07:08:55.898Z",
"app/learn/fundamentals/admin/page.mdx": "2025-03-21T08:25:13.754Z",
"app/learn/fundamentals/workflows/long-running-workflow/page.mdx": "2025-03-18T08:02:14.085Z",
"app/learn/fundamentals/workflows/constructor-constraints/page.mdx": "2025-02-12T13:55:33.437Z",
"app/learn/fundamentals/data-models/write-migration/page.mdx": "2025-03-18T08:00:44.980Z",
@@ -68,8 +68,8 @@ export const generatedEditDates = {
"app/learn/fundamentals/module-links/custom-columns/page.mdx": "2025-03-11T13:29:54.752Z",
"app/learn/fundamentals/module-links/directions/page.mdx": "2025-03-17T12:52:06.161Z",
"app/learn/fundamentals/module-links/page.mdx": "2025-03-11T13:39:14.345Z",
"app/learn/fundamentals/module-links/query/page.mdx": "2025-03-11T15:35:10.605Z",
"app/learn/fundamentals/modules/db-operations/page.mdx": "2025-03-18T15:10:57.351Z",
"app/learn/fundamentals/module-links/query/page.mdx": "2025-03-21T09:14:54.943Z",
"app/learn/fundamentals/modules/db-operations/page.mdx": "2025-03-21T09:21:46.901Z",
"app/learn/fundamentals/modules/multiple-services/page.mdx": "2025-03-18T15:11:44.632Z",
"app/learn/fundamentals/modules/page.mdx": "2025-03-18T07:51:09.049Z",
"app/learn/debugging-and-testing/instrumentation/page.mdx": "2025-02-24T08:12:53.132Z",
@@ -117,6 +117,6 @@ export const generatedEditDates = {
"app/learn/configurations/medusa-config/page.mdx": "2025-03-11T14:27:04.528Z",
"app/learn/configurations/ts-aliases/page.mdx": "2025-02-11T16:57:46.683Z",
"app/learn/production/worker-mode/page.mdx": "2025-03-11T15:21:50.906Z",
"app/learn/fundamentals/module-links/read-only/page.mdx": "2025-03-17T14:18:29.924Z",
"app/learn/fundamentals/module-links/read-only/page.mdx": "2025-03-21T09:14:54.944Z",
"app/learn/fundamentals/data-models/properties/page.mdx": "2025-03-18T07:57:17.826Z"
}
File diff suppressed because it is too large Load Diff
@@ -2,7 +2,8 @@
sidebar_label: "Vercel"
---
import { Prerequisites } from "docs-ui"
import RewritesError from "../../../troubleshooting/_sections/storefront/rewrites.mdx"
import { Prerequisites, DetailsList } from "docs-ui"
export const metadata = {
title: `Deploy Medusa Next.js to Vercel`,
@@ -143,3 +144,12 @@ Once the redeployment is done, test out the storefront by going to its URL. Try
## Troubleshooting
If youre running into issues in your storefront, find the logs in your Vercel projects dashboard under the Logs tab.
<DetailsList
sections={[
{
title: "Login Page Error",
content: <RewritesError />
}
]}
/>
@@ -337,7 +337,7 @@ export default defineLink(
},
ProductModule.linkable.product,
{
readOnly: true
readOnly: true,
}
)
```
@@ -1610,7 +1610,7 @@ export default defineMiddlewares({
"first_name",
"last_name",
"content",
"created_at"
"created_at",
],
}),
],
@@ -24,13 +24,29 @@ The `list` method is used in the example snippets of this reference, but you can
```ts
const posts = await postModuleService.listPosts({
name: "My Post 2",
title: "My Post 2",
})
```
If you pass a property with its value, only records whose properties exactly match the value are selected.
In the example above, only posts having the name `My Post 2` are retrieved.
In the example above, only posts having the title `My Post 2` are retrieved.
---
## Doesn't Match Exact Value
```ts
const posts = await postModuleService.listPosts({
title: {
$ne: "My Post",
},
})
```
To find records with a property that doesn't match a value, pass an object with a `$ne` property. Its value is the value that a record's property shouldn't match.
In the example above, only posts that don't have the title `My Post` are retrieved.
---
@@ -51,11 +67,11 @@ In the example above, only posts having either `50` or `100` views are retrieved
---
## Don't Match Values
## Don't Match Multiple Values
```ts
const posts = await postModuleService.listPosts({
name: {
title: {
$nin: [
"My Post",
],
@@ -65,7 +81,7 @@ const posts = await postModuleService.listPosts({
To find records with a property that doesn't match one or more values, pass an object with a `$nin` property. Its value is an array of multiple values that a record's property shouldn't match.
In the example above, only posts that don't have the name `My Post` are retrieved.
In the example above, only posts that don't have the title `My Post` are retrieved.
---
@@ -73,13 +89,13 @@ In the example above, only posts that don't have the name `My Post` are retrieve
<Note>
This filter only applies to text-like properties, including `id` and `enum` properties.
This filter only applies to text-like properties, including `text`, `id`, and `enum` properties.
</Note>
```ts
const posts = await postModuleService.listPosts({
name: {
title: {
$like: "My%",
},
})
@@ -87,7 +103,37 @@ const posts = await postModuleService.listPosts({
To perform a `like` filter on a record's property, set the property's value to an object with a `$like` property. Its value is the string to use when applying the `like` filter.
The example above matches all posts whose name starts with `My`.
The example above matches all posts whose title starts with `My`.
---
## Filter by Null or Not Null
To retrieve records with a property that is `null`, set the property's value to `null`.
For example:
```ts
const posts = await postModuleService.listPosts({
published_at: null,
})
```
In the example above, only posts that have a `null` publish date are retrieved.
On the other hand, to retrieve records with a property that isn't `null`, set the property's value to an object with a `$ne` property.
For example:
```ts
const posts = await postModuleService.listPosts({
published_at: {
$ne: null,
},
})
```
In the example above, only posts that have a publish date are retrieved.
---
@@ -137,6 +183,19 @@ The `dateTime` property also stores the time. So, when matching for an exact day
In this example, you retrieve the current date twice: once to set its time to `00:00:00`, and another to set its time `23:59:59`. Then, you retrieve posts whose `published_at` property is between `00:00:00` and `23:59:59` of today.
### Example: Range Filter on Number Property
```ts
const posts = await postModuleService.listPosts({
views: {
$gte: 50,
$lte: 100,
},
})
```
In the example above, only posts with `views` between `50` and `100` are retrieved.
---
## Apply Or Condition
@@ -145,7 +204,7 @@ In this example, you retrieve the current date twice: once to set its time to `0
const posts = await postModuleService.listPosts({
$or: [
{
name: "My Post",
title: "My Post",
},
{
published_at: {
@@ -158,4 +217,60 @@ const posts = await postModuleService.listPosts({
To use an `or` condition, pass to the filter object the `$or` property, whose value is an array of filters.
In the example above, posts whose name is `My Post` or their `published_at` date is less than the current date and time are retrieved.
In the example above, posts whose title is `My Post` or their `published_at` date is less than the current date and time are retrieved.
---
## Apply And Condition
```ts
const posts = await postModuleService.listPosts({
$and: [
{
title: "My Post",
},
{
published_at: {
$lt: new Date(),
},
},
],
})
```
To use an `and` condition, pass to the filter object the `$and` property, whose value is an array of filters.
In the example above, only posts whose title is `My Post` and their `published_at` date is less than the current date and time are retrieved.
---
## Complex Filters Example
```ts
const posts = await postModuleService.listPosts({
$or: [
{
$and: [
{ views: { $gte: 50 } },
{
published_at: {
$gte: new Date(new Date().getFullYear(), 0, 1),
},
},
],
},
{
title: {
$like: "%Featured%",
},
},
],
})
```
In the example above, posts are retrieved if they meet either of the following conditions:
1. The post has at least `50` views and was published after the beginning of the current year.
2. The post's title contains the word `Featured`.
By combining `and` and `or` conditions, you can create complex filters to retrieve records that meet specific criteria.
@@ -0,0 +1,51 @@
If you see the following error in the Medusa Admin's console:
```bash
Blocked request. This host (X) is not allowed. To allow this host, add X to server.allowedHosts in vite.config.js.
```
Where `X` is the host that's being blocked. For example, `example.com`.
## Why this Error Occurred
This error occurs if you deploy Medusa but are using development mode (`NODE_ENV=development`). This can happen accidentally or unintentionally, but Medusa defaults `NODE_ENV` to `production`.
## How to Fix it
### Option 1: Use Production Mode
To resolve this error, ensure that you're running Medusa in production mode. You can set the `NODE_ENV` environment variable to `production` when starting Medusa:
```bash
NODE_ENV=production
```
### Option 2: Allow the Host
If you intentionally want to use development mode in your deployed Medusa instance, you can allow the host that's being blocked using the `admin.vite` configuration in `medusa-config.ts`.
For example:
```ts title="medusa-config.ts"
module.exports = defineConfig({
// ...
admin: {
vite: () => {
return {
server: {
allowedHosts: [".example.com"],
},
}
},
},
})
```
In the above example, you allow the host `example.com` to access the Medusa Admin. Make sure that when you replace `example.com` with your actual host, you include the leading `.` before the domain name.
---
## Additional Resources
- [Environment Variables](!docs!/learn/fundamentals/environment-variables)
- [admin.vite Configuration](!docs!/learn/configurations/medusa-config#vite)
@@ -0,0 +1,22 @@
If you send a request to an API route and receive the following error:
```json
{
"type": "invalid_data",
"message": "Invalid request: Unrecognized fields: 'additional_data'"
}
```
## Why this Error Occured
This error occurs when you send the `additional_data` request body parameter to a route that doesn't support it.
The [Additional Data property](https://docs.medusajs.com/learn/fundamentals/api-routes/additional-data) is useful to pass custom data to an API route, but it's not supported by all API routes.
---
## How to Fix it
For the list of API routes that support passing `additional_data`, refer to the [Additional Data documentation](https://docs.medusajs.com/learn/fundamentals/api-routes/additional-data).
If the route you need isn't on the list, you have to create a custom API route with your desired functionality.
@@ -0,0 +1,23 @@
If you get the following error after creating a new data model in your Medusa application:
```bash
error: Error: Cannot define field(s) "created_at,updated_at,deleted_at" as they are implicitly defined on every model
```
The error may include the three fields, or only some of them, based on which fields you're trying to define in the data model.
## Why this Error Occurred
This error occurs because you're trying to define the `created_at`, `updated_at`, or `deleted_at` properties on a new data model. These properties are implicitly defined on every data model in Medusa and can't be redefined.
---
## How to Fix it
To resolve this error, remove the `created_at`, `updated_at`, and `deleted_at` properties from your data model definition. You'll still be able to use these properties in your application, but you can't redefine them in your data models.
---
## Additional Resources
- [Data Model's Default Properties](!docs!/learn/fundamentals/data-models/properties#data-models-default-properties)
@@ -0,0 +1,55 @@
If you get the following error in your Medusa application's terminal:
```bash
Trying to query by not existing property LinkModel.X.
```
Where `X` is the name of a data model. For example, `LinkModel.cart`.
## Why this Error Occurred
This error occurs when you're using Query and you're trying to filter by a linked module, which isn't allowed.
For example, assuming you have a `Post` data model and you linked it to the `Cart` data model, this isn't allowed:
```ts
const { data } = await query.graph({
entity: "post",
fields: ["*"],
filter: {
cart: {
id: "cart_123",
},
},
})
```
You can't filter your custom `post` data model by the ID of their linked cart.
---
## How to Fix it
You need to query the link's table directly and apply the filters on its ID columns. For example:
```ts
import PostCartLink from "../links/post-cart"
// ...
const { data } = await query.graph({
entity: PostCartLink.entryPoint,
fields: ["post.*", "cart.*"],
filters: {
cart_id: "cart_123",
},
})
```
In the above example, you query the `PostCartLink` data model directly and apply the filters to the `cart_id` field, which holds the ID of the cart linked to the post. You'll then only retrieve the posts linked to the cart with the ID `cart_123`.
---
## Additional Resources
- [Query](!docs!/learn/fundamentals/module-links/query#apply-filters-and-pagination-on-linked-records)
@@ -0,0 +1,86 @@
If you get the following error when using Query to retrieve records of your custom data model:
```bash
service.list is not a function
```
## Why this Error Occurred
To retrieve records of your data model, Query uses the `listX` method of your module's service.
For example, if you have a Blog Module and you are trying to retrieve posts, Query will try to call the `listPost` method of the Blog Module's service. If it doesn't find the method, it will throw the above error.
---
## How to Fix it
### Option 1: Extend Service Factory
To resolve this error, make sure that your module's service has a `listX` method that returns the records of your data model.
This method is generated for you if your service extends `MedusaService`:
```ts title="src/modules/blog/service.ts"
import { MedusaService } from "@medusajs/framework/utils"
import Post from "./models/post"
class BlogModuleService extends MedusaService({
Post,
}){
}
export default BlogModuleService
```
In the above example, the `listPost` method is generated for you because the `BlogModuleService` extends `MedusaService`.
### Option 2: Implement the Method
If your module is returning data from a third-party service, or you have some custom mechanism to define and manage your data models, then you need to implement the `list` or just `list` method in your service.
For example:
```ts title="src/modules/blog/service.ts"
type BlogModuleOptions = {
apiKey: string
}
export default class BlogModuleService {
private client
constructor({}, options: BlogModuleOptions) {
this.client = new Client(options)
}
async list(
filter: {
id: string | string[]
}
) {
return this.client.getPosts(filter)
/**
* Example of returned data:
*
* [
* {
* "id": "post_123",
* "product_id": "prod_321"
* },
* {
* "id": "post_456",
* "product_id": "prod_654"
* }
* ]
*/
}
}
```
---
## Additional Resources
- [Query](!docs!/learn/fundamentals/module-links/query)
- [Service Factory documentation](!docs!/learn/fundamentals/modules/service-factory)
- [Service Factory reference](../../../service-factory-reference/page.mdx)
- [Example: Read-Only Module Link for Virtual Data Models](!docs!/learn/fundamentals/module-links/read-only#example-read-only-module-link-for-virtual-data-models)
@@ -0,0 +1,18 @@
If you send a request to the `/store/products` or `/store/products/:id` API routes and receive the following error in the response:
```bash
{
"type": "invalid_data",
"message": "Publishable key needs to have a sales channel configured."
}
```
## Why this Error Occurred
This error means you passed a valid `x-publishable-api-key` header, but the key does not have a sales channel configured. The sales channel is required to make requests to the `/store/products` and `/store/products/:id` routes, as it's used to retrieve products available in that sales channel.
---
## How to Fix it
To resolve this error, you need to add at least one sales channel to your publishable API key. Refer to the [Manage Publishable API Key User Guide](!user-guide!/settings/developer/publishable-api-keys#manage-publishable-api-keys-sales-channels) to learn how to do that.
@@ -0,0 +1,33 @@
If you receive the following error response when you send a request to a `/store` route:
```json
{
"type": "not_allowed",
"message": "Publishable API key required in the request header: x-publishable-api-key. You can manage your keys in settings in the dashboard."
}
```
## Why this Error Occurred
This error occurs because the request is missing the `x-publishable-api-key` header. The `x-publishable-api-key` header is required for all requests to the `/store` route.
---
## How to Fix it
To resolve this error, add the `x-publishable-api-key` header to your request. You can find your publishable API key in the [Medusa Admin Dashboard](!user-guide!/settings/developer/publishable-api-keys).
For example:
```bash
curl -X GET https://localhost:9000/store/products \
-H "x-publishable-api-key: your-publishable-api-key"
```
Where `your-publishable-api-key` is your publishable API key.
---
## Additional Resources
- [API reference](!api!/store#publishable-api-key)
@@ -0,0 +1,32 @@
The Next.js Starter Storefront uses parallel routes to show account pages. However, there's a [reported error](https://github.com/vercel/next.js/issues/71626) when hosting Next.js with parallel routes on Google's Cloud Run, where the error stops working.
## Why this Error Occurred
This error occurs because Google Cloud Run decodes chunk URLs, but Next.js expects them to be encoded.
---
## How to Fix it
To resolve the error, add the following rewrites in your Next.js Starter Storefront's `next.config.ts` file:
```ts title="next.config.ts"
const nextConfig = {
// ... other config
rewrites: async () => {
return {
beforeFiles: [
{
source: "/_next/static/chunks/app/:folder*/@login/:path*",
destination: "/_next/static/chunks/app/:folder*/%40login/:path*",
},
// Repeat this pattern if other similar errors occur
],
afterFiles: [],
fallback: [],
}
},
}
```
You can add the rewrite to other parallel routes you have in your application. For example, if you have a `/@dashboard` route, you can add a rewrite for it as well.
@@ -0,0 +1,45 @@
If you get the following error when you start the Medusa application:
```bash
Error: Step X is already defined in workflow.
```
Where `X` is any step, such as `create-remote-link`.
## Why this Error Occurred
This error indicates that you're re-using a step in a workflow, meaning that more than one step in the workflow have the same name.
---
## How to Fix it
To resolve this error, use the `config` method of a step to specify a custom name within the workflow's scope. For example:
```ts
const helloWorkflow = createWorkflow(
"hello",
() => {
const { data: products } = useQueryGraphStep({
entity: "product",
fields: ["id"],
})
// ✓ No error occurs, the step has a different ID.
const { data: customers } = useQueryGraphStep({
entity: "customer",
fields: ["id"],
}).config({ name: "fetch-customers" })
}
)
```
In the above example, you use the `config` method on the second `useQueryGraphStep` usage to change its name to `fetch-customers`.
Make sure to change the name of every usage after the first one in a workflow.
---
## Additional Resources
- [Multiple Step Usage in Workflow documentation](https://docs.medusajs.com/learn/fundamentals/workflows/multiple-step-usage)
@@ -0,0 +1,9 @@
import AdditionalDataError from "../_sections/api-routes/additional-data.mdx"
export const metadata = {
title: `Unrecognized fields \`additiona_data\` Error`,
}
# {metadata.title}
<AdditionalDataError />
@@ -0,0 +1,9 @@
import DataModelDefaults from "../../_sections/data-models/default-fields.mdx"
export const metadata = {
title: `Can't define fields Error`,
}
# {metadata.title}
<DataModelDefaults />
@@ -0,0 +1,9 @@
import AdminBlockedRequest from "../../_sections/admin/blocked-request.mdx"
export const metadata = {
title: `Blocked Request Error in Medusa Admin`,
}
# {metadata.title}
<AdminBlockedRequest />
@@ -0,0 +1,9 @@
import RewritesTroubleshooting from "../_sections/storefront/rewrites.mdx"
export const metadata = {
title: `Next.js Starter Storefront Login Page Error on Google Cloud Run`,
}
# {metadata.title}
<RewritesTroubleshooting />
@@ -0,0 +1,9 @@
import NotExistingPropertyError from "../../_sections/query/not-existing-property.mdx"
export const metadata = {
title: `Trying to query by not existing property Error`,
}
# {metadata.title}
<NotExistingPropertyError />
@@ -0,0 +1,9 @@
import ServiceListError from "../../_sections/query/service-list.mdx"
export const metadata = {
title: `service.list is not a function Error`,
}
# {metadata.title}
<ServiceListError />
@@ -0,0 +1,9 @@
import PakTroubleshooting from "../_sections/storefront/pak.mdx"
export const metadata = {
title: `Publishable API key required Error`,
}
# {metadata.title}
<PakTroubleshooting />
@@ -0,0 +1,9 @@
import PakScTroubleshooting from "../_sections/storefront/pak-sc.mdx"
export const metadata = {
title: `Publishable API needs to have a sales channel Error`,
}
# {metadata.title}
<PakScTroubleshooting />
@@ -1,24 +0,0 @@
export const metadata = {
title: `Workflow Errors`,
}
# {metadata.title}
## When-Then Error: Handler for action X Not Found
The following error may occur in production if you use a `when-then` block in your workflow:
```plain
custom-workflow:when-then-01JE8Z0M1FXSE2NCK1G04S0RR2:invoke - Handler for action \"when-then-01JE8Z0M1FXSE2NCK1G04S0RR2\" not found...
```
This occurs if the `when-then` block doesn't return a step's result and doesn't have a name specified. You can resolve it by passing a name as a first parameter of `when`:
```ts
const result = when(
"custom-when-condition"
// ... rest of the parameters
)
```
Learn more about passing a name for `when-then` in [this documentation](!docs!/learn/fundamentals/workflows/conditions#specify-name-for-when-then)
@@ -0,0 +1,9 @@
import StepXDefined from "../../_sections/workflows/step-x-defined.mdx"
export const metadata = {
title: `Step X is already defined in workflow Error`,
}
# {metadata.title}
<StepXDefined />
@@ -0,0 +1,49 @@
export const metadata = {
title: `Handler for action X Not Found Workflow Error`,
}
# {metadata.title}
The following error may occur in production if you use a `when-then` block in your workflow:
```plain
custom-workflow:when-then-01JE8Z0M1FXSE2NCK1G04S0RR2:invoke - Handler for action \"when-then-01JE8Z0M1FXSE2NCK1G04S0RR2\" not found...
```
## Why this Error Occured
This error occurs if the `when-then` block doesn't return a step's result and doesn't have a name specified.
For example:
```ts
when(input, (input) => !input.is_active)
.then(() => {
console.log("not returning anything")
})
```
The above `when-then` block doesn't return a step's result, which causes the error.
---
## How to Fix it
You can resolve this error by passing a name as a first parameter of `when`:
```ts
const result = when(
"custom-when-condition",
input,
(input) => !input.is_active
)
.then(() => {
console.log("not returning anything")
})
```
---
## Additional Resources
- [When-Then documentation](!docs!/learn/fundamentals/workflows/conditions#specify-name-for-when-then)
+13 -4
View File
@@ -102,7 +102,7 @@ export const generatedEditDates = {
"app/create-medusa-app/page.mdx": "2025-01-16T10:00:25.975Z",
"app/deployment/admin/vercel/page.mdx": "2024-10-16T08:10:29.377Z",
"app/deployment/medusa-application/railway/page.mdx": "2025-03-11T08:56:02.100Z",
"app/deployment/storefront/vercel/page.mdx": "2025-01-06T12:19:31.142Z",
"app/deployment/storefront/vercel/page.mdx": "2025-03-21T07:19:24.818Z",
"app/deployment/page.mdx": "2024-11-25T14:31:45.277Z",
"app/integrations/page.mdx": "2025-02-26T11:37:17.771Z",
"app/medusa-cli/page.mdx": "2024-08-28T11:25:32.382Z",
@@ -132,7 +132,7 @@ export const generatedEditDates = {
"app/service-factory-reference/methods/retrieve/page.mdx": "2024-07-31T17:01:33+03:00",
"app/service-factory-reference/methods/soft-delete/page.mdx": "2024-07-31T17:01:33+03:00",
"app/service-factory-reference/methods/update/page.mdx": "2024-07-31T17:01:33+03:00",
"app/service-factory-reference/tips/filtering/page.mdx": "2024-07-31T17:01:33+03:00",
"app/service-factory-reference/tips/filtering/page.mdx": "2025-03-21T08:32:39.125Z",
"app/service-factory-reference/page.mdx": "2024-07-26T14:40:56+00:00",
"app/storefront-development/cart/context/page.mdx": "2025-01-06T16:00:34.296Z",
"app/storefront-development/cart/create/page.mdx": "2025-02-26T11:44:58.922Z",
@@ -5578,7 +5578,6 @@ export const generatedEditDates = {
"references/types/DmlTypes/types/types.DmlTypes.KnownDataTypes/page.mdx": "2024-12-17T16:57:19.922Z",
"references/types/DmlTypes/types/types.DmlTypes.RelationshipTypes/page.mdx": "2024-12-10T14:54:55.435Z",
"app/recipes/commerce-automation/restock-notification/page.mdx": "2025-03-17T07:36:21.511Z",
"app/troubleshooting/workflow-errors/page.mdx": "2024-12-11T08:44:36.598Z",
"app/integrations/guides/shipstation/page.mdx": "2025-02-26T11:21:46.879Z",
"app/nextjs-starter/guides/customize-stripe/page.mdx": "2024-12-25T14:48:55.877Z",
"references/core_flows/Cart/Workflows_Cart/functions/core_flows.Cart.Workflows_Cart.listShippingOptionsForCartWithPricingWorkflow/page.mdx": "2025-03-04T13:33:40.584Z",
@@ -6061,5 +6060,15 @@ export const generatedEditDates = {
"app/nextjs-starter/guides/revalidate-cache/page.mdx": "2025-03-18T08:47:59.628Z",
"app/storefront-development/cart/totals/page.mdx": "2025-03-18T09:20:59.533Z",
"app/storefront-development/checkout/order-confirmation/page.mdx": "2025-03-18T09:44:14.561Z",
"app/how-to-tutorials/tutorials/product-reviews/page.mdx": "2025-03-19T13:00:56.901Z"
"app/how-to-tutorials/tutorials/product-reviews/page.mdx": "2025-03-19T13:00:56.901Z",
"app/troubleshooting/api-routes/page.mdx": "2025-03-21T07:17:56.248Z",
"app/troubleshooting/data-models/default-fields/page.mdx": "2025-03-21T06:59:06.775Z",
"app/troubleshooting/medusa-admin/blocked-request/page.mdx": "2025-03-21T06:53:34.854Z",
"app/troubleshooting/nextjs-starter-rewrites/page.mdx": "2025-03-21T07:09:08.901Z",
"app/troubleshooting/query/filter-linked/page.mdx": "2025-03-21T07:07:51.046Z",
"app/troubleshooting/query/service-list/page.mdx": "2025-03-21T07:08:32.825Z",
"app/troubleshooting/storefront-missing-pak/page.mdx": "2025-03-21T07:08:52.294Z",
"app/troubleshooting/storefront-pak-sc/page.mdx": "2025-03-21T07:08:57.546Z",
"app/troubleshooting/workflow-errors/step-x-defined/page.mdx": "2025-03-21T07:09:02.741Z",
"app/troubleshooting/workflow-errors/when-then/page.mdx": "2025-03-21T08:35:45.145Z"
}
+38 -2
View File
@@ -1247,6 +1247,10 @@ export const filesMap = [
"filePath": "/www/apps/resources/app/tools/page.mdx",
"pathname": "/tools"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/api-routes/page.mdx",
"pathname": "/troubleshooting/api-routes"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/cors-errors/page.mdx",
"pathname": "/troubleshooting/cors-errors"
@@ -1255,6 +1259,10 @@ export const filesMap = [
"filePath": "/www/apps/resources/app/troubleshooting/create-medusa-app-errors/page.mdx",
"pathname": "/troubleshooting/create-medusa-app-errors"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/data-models/default-fields/page.mdx",
"pathname": "/troubleshooting/data-models/default-fields"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/database-errors/page.mdx",
"pathname": "/troubleshooting/database-errors"
@@ -1279,25 +1287,53 @@ export const filesMap = [
"filePath": "/www/apps/resources/app/troubleshooting/general-errors/page.mdx",
"pathname": "/troubleshooting/general-errors"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/medusa-admin/blocked-request/page.mdx",
"pathname": "/troubleshooting/medusa-admin/blocked-request"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/medusa-admin/no-widget-route/page.mdx",
"pathname": "/troubleshooting/medusa-admin/no-widget-route"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/nextjs-starter-rewrites/page.mdx",
"pathname": "/troubleshooting/nextjs-starter-rewrites"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/page.mdx",
"pathname": "/troubleshooting"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/query/filter-linked/page.mdx",
"pathname": "/troubleshooting/query/filter-linked"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/query/service-list/page.mdx",
"pathname": "/troubleshooting/query/service-list"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/s3/page.mdx",
"pathname": "/troubleshooting/s3"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/storefront-missing-pak/page.mdx",
"pathname": "/troubleshooting/storefront-missing-pak"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/storefront-pak-sc/page.mdx",
"pathname": "/troubleshooting/storefront-pak-sc"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/test-errors/page.mdx",
"pathname": "/troubleshooting/test-errors"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/workflow-errors/page.mdx",
"pathname": "/troubleshooting/workflow-errors"
"filePath": "/www/apps/resources/app/troubleshooting/workflow-errors/step-x-defined/page.mdx",
"pathname": "/troubleshooting/workflow-errors/step-x-defined"
},
{
"filePath": "/www/apps/resources/app/troubleshooting/workflow-errors/when-then/page.mdx",
"pathname": "/troubleshooting/workflow-errors/when-then"
},
{
"filePath": "/www/apps/resources/references/api_key/IApiKeyModuleService/methods/api_key.IApiKeyModuleService.authenticate/page.mdx",
@@ -1071,6 +1071,14 @@ const generatedgeneratedCommerceModulesSidebarSidebar = {
"sort_sidebar": "alphabetize",
"description": "Learn how to use the Cart Module in your customizations on the Medusa application server.",
"children": [
{
"loaded": true,
"isPathHref": true,
"type": "ref",
"title": "Abandoned Cart Notification",
"path": "https://docs.medusajs.com/resources/how-to-tutorials/tutorials/abandoned-cart",
"children": []
},
{
"loaded": true,
"isPathHref": true,
@@ -50,7 +50,24 @@ const generatedgeneratedTroubleshootingSidebarSidebar = {
"loaded": true,
"isPathHref": true,
"type": "category",
"title": "Medusa Application",
"title": "Upgrade",
"initialOpen": true,
"children": [
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/troubleshooting/errors-after-upgrading",
"title": "Errors After Upgrading",
"children": []
}
]
},
{
"loaded": true,
"isPathHref": true,
"type": "category",
"title": "Framework",
"initialOpen": true,
"children": [
{
@@ -80,10 +97,42 @@ const generatedgeneratedTroubleshootingSidebarSidebar = {
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/troubleshooting/workflow-errors",
"title": "Workflow Errors",
"children": []
"type": "sub-category",
"title": "Query",
"children": [
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/troubleshooting/query/filter-linked",
"title": "Not Exising Property",
"children": []
}
]
},
{
"loaded": true,
"isPathHref": true,
"type": "sub-category",
"title": "Workflows",
"children": [
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/troubleshooting/workflow-errors/when-then",
"title": "Handler Not Found",
"children": []
},
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/troubleshooting/workflow-errors/step-x-defined",
"title": "Step Already Defined",
"children": []
}
]
},
{
"loaded": true,
@@ -95,40 +144,6 @@ const generatedgeneratedTroubleshootingSidebarSidebar = {
}
]
},
{
"loaded": true,
"isPathHref": true,
"type": "category",
"title": "Admin Development",
"initialOpen": true,
"children": [
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/troubleshooting/medusa-admin/no-widget-route",
"title": "Widget or Route not Showing",
"children": []
}
]
},
{
"loaded": true,
"isPathHref": true,
"type": "category",
"title": "Upgrade",
"initialOpen": true,
"children": [
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/troubleshooting/errors-after-upgrading",
"title": "Errors After Upgrading",
"children": []
}
]
},
{
"loaded": true,
"isPathHref": true,
@@ -162,6 +177,80 @@ const generatedgeneratedTroubleshootingSidebarSidebar = {
"children": []
}
]
},
{
"loaded": true,
"isPathHref": true,
"type": "category",
"title": "Admin Development",
"initialOpen": true,
"children": [
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/troubleshooting/medusa-admin/no-widget-route",
"title": "Widget or Route not Showing",
"children": []
},
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/troubleshooting/medusa-admin/blocked-request",
"title": "Blocked Request",
"children": []
}
]
},
{
"loaded": true,
"isPathHref": true,
"type": "category",
"title": "Storefront",
"initialOpen": true,
"children": [
{
"loaded": true,
"isPathHref": true,
"type": "sub-category",
"title": "Next.js Starter",
"children": [
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/troubleshooting/nextjs-starter-rewrites",
"title": "Cloud Run Error",
"children": []
}
]
},
{
"loaded": true,
"isPathHref": true,
"type": "sub-category",
"title": "Publishable API Key Errors",
"children": [
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/troubleshooting/storefront-missing-pak",
"title": "Missing Publishable API Key",
"children": []
},
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/troubleshooting/storefront-pak-sc",
"title": "Sales Channels Error",
"children": []
}
]
}
]
}
]
}
+5
View File
@@ -158,6 +158,11 @@ const nextConfig = {
destination: `${process.env.NEXT_PUBLIC_BASE_URL}/learn/configurations/medusa-config`,
permanent: true,
},
{
source: "/troubleshooting/workflow-errors",
destination: "/troubleshooting/workflow-errors/when-then",
permanent: true,
},
]
},
outputFileTracingExcludes: {
+89 -28
View File
@@ -32,7 +32,19 @@ export const troubleshootingSidebar = [
},
{
type: "category",
title: "Medusa Application",
title: "Upgrade",
initialOpen: true,
children: [
{
type: "link",
path: "/troubleshooting/errors-after-upgrading",
title: "Errors After Upgrading",
},
],
},
{
type: "category",
title: "Framework",
initialOpen: true,
children: [
{
@@ -51,9 +63,31 @@ export const troubleshootingSidebar = [
title: "Importing from /dist",
},
{
type: "link",
path: "/troubleshooting/workflow-errors",
title: "Workflow Errors",
type: "sub-category",
title: "Query",
children: [
{
type: "link",
path: "/troubleshooting/query/filter-linked",
title: "Not Exising Property",
},
],
},
{
type: "sub-category",
title: "Workflows",
children: [
{
type: "link",
path: "/troubleshooting/workflow-errors/when-then",
title: "Handler Not Found",
},
{
type: "link",
path: "/troubleshooting/workflow-errors/step-x-defined",
title: "Step Already Defined",
},
],
},
{
type: "link",
@@ -62,30 +96,6 @@ export const troubleshootingSidebar = [
},
],
},
{
type: "category",
title: "Admin Development",
initialOpen: true,
children: [
{
type: "link",
path: "/troubleshooting/medusa-admin/no-widget-route",
title: "Widget or Route not Showing",
},
],
},
{
type: "category",
title: "Upgrade",
initialOpen: true,
children: [
{
type: "link",
path: "/troubleshooting/errors-after-upgrading",
title: "Errors After Upgrading",
},
],
},
{
type: "category",
title: "Frontend",
@@ -110,4 +120,55 @@ export const troubleshootingSidebar = [
},
],
},
{
type: "category",
title: "Admin Development",
initialOpen: true,
children: [
{
type: "link",
path: "/troubleshooting/medusa-admin/no-widget-route",
title: "Widget or Route not Showing",
},
{
type: "link",
path: "/troubleshooting/medusa-admin/blocked-request",
title: "Blocked Request",
},
],
},
{
type: "category",
title: "Storefront",
initialOpen: true,
children: [
{
type: "sub-category",
title: "Next.js Starter",
children: [
{
type: "link",
path: "/troubleshooting/nextjs-starter-rewrites",
title: "Cloud Run Error",
},
],
},
{
type: "sub-category",
title: "Publishable API Key Errors",
children: [
{
type: "link",
path: "/troubleshooting/storefront-missing-pak",
title: "Missing Publishable API Key",
},
{
type: "link",
path: "/troubleshooting/storefront-pak-sc",
title: "Sales Channels Error",
},
],
},
],
},
]