gatsbyjs/gatsby · error
A recipe must be specified
Error message
A recipe must be specified
What it means
Thrown by the `resolvingRecipe` state of the gatsby-recipes xstate machine (recipe-machine/index.js:45). The state tries three resolution paths in order: explicit `context.src`, a `recipePath`+`projectRoot` pair, else throws. The throw is caught by the machine's `onError` and routed to `doneError` with a friendlier message.
Source
Thrown at deprecated-packages/gatsby-recipes/src/recipe-machine/index.js:45
commands: [],
stepResources: [],
inputs: {},
},
states: {
resolvingRecipe: {
invoke: {
id: `resolveRecipe`,
src: async (context, _event) => {
if (context.src) {
return context.src
} else if (context.recipePath && context.projectRoot) {
const recipe = await resolveRecipe(
context.recipePath,
context.projectRoot
)
return recipe
} else {
throw new Error(`A recipe must be specified`)
}
},
onError: {
target: `doneError`,
actions: assign({
error: (context, _event) => {
debug(`error resolving recipe`)
return {
error: `Could not resolve recipe "${context.recipePath}"`,
}
},
}),
},
onDone: {
target: `parsingRecipe`,
actions: assign({
recipeSrc: (_context, event) => event.data,
}),View on GitHub (pinned to 8b06340921)
Solutions
- Pass either a full `src` string (MDX content) or both `recipePath` and `projectRoot` to the machine's context.
- If using the CLI, supply the recipe argument: `gatsby recipes <name>`.
- Validate that `recipePath` is a non-empty string before starting the machine.
Example fix
// before
Machine.interpret(recipeMachine).start({ src: undefined, recipePath: null, projectRoot: null })
// after
Machine.interpret(recipeMachine).start({
recipePath: `adding-typescript`,
projectRoot: process.cwd(),
}) Defensive patterns
Strategy: validation
Validate before calling
function machineHasRecipeInput(context) {
return Boolean(context.src) || Boolean(context.recipePath && context.projectRoot)
} Type guard
function isRecipeContextValid(ctx) {
return typeof ctx.src === 'string' && ctx.src.trim() !== ''
|| (typeof ctx.recipePath === 'string' && ctx.recipePath !== '' && typeof ctx.projectRoot === 'string')
} Try / catch
try {
await service.send({ type: 'START' })
} catch (e) {
if (/A recipe must be specified/.test(e.message)) { /* ask user for recipe */ }
} Prevention
- Always populate recipePath and projectRoot on machine context.
- Validate context shape before starting the machine.
- When using the CLI, always pass a recipe argument.
When it happens
Trigger: Starting the recipe machine without setting `src`, or without setting both `recipePath` and `projectRoot`; passing a falsy/empty recipe path; misconfiguring the machine's initial context.
Common situations: Programmatically invoking the recipe machine from tooling that forgot to populate context; calling `recipes.run()` with no argument; passing a recipe path that is an empty string.
Related errors
- MissingInfoError
- Your gatsby-config.js format is currently not supported by G
- Did not recognize ${curr}
- ${JSON.stringify(result)}
- {"fetchError":"Could not fetch ${pathOrUrl} from official re
AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13).
Data as JSON: /api/errors/0070c197efd7bff4.
Report an issue: GitHub.