mastra-ai/mastra · error · Error
Step "${stepName}" not found in lesson "${lessonName}".
Error message
Step "${stepName}" not found in lesson "${lessonName}". What it means
After locating the lesson directory, readCourseStep looks for a `.md` file whose name (with numeric prefix and `.md` extension stripped) equals stepName. If no file matches, it throws this error: the step does not exist inside the given lesson.
Source
Thrown at packages/mcp-docs-server/src/tools/course.ts:199
return response.json() as Promise<{ success: boolean; id: string; key: string; message: string }>;
}
async function readCourseStep(lessonName: string, stepName: string, _isFirstStep: boolean = false): Promise<string> {
// Find the lesson directory that matches the name
const lessonDirs = await fs.readdir(courseDir);
const lessonDir = lessonDirs.find(dir => dir.replace(/^\d+-/, '') === lessonName);
if (!lessonDir) {
throw new Error(`Lesson "${lessonName}" not found.`);
}
// Find the step file that matches the name
const lessonPath = path.join(courseDir, lessonDir);
const files = await fs.readdir(lessonPath);
const stepFile = files.find(f => f.endsWith('.md') && f.replace(/^\d+-/, '').replace('.md', '') === stepName);
if (!stepFile) {
throw new Error(`Step "${stepName}" not found in lesson "${lessonName}".`);
}
const filePath = path.join(courseDir, lessonDir, stepFile);
try {
const content = await fs.readFile(filePath, 'utf-8');
return wrapContentInPrompt(content);
} catch (error) {
throw new Error(`Failed to read step "${stepName}" in lesson "${lessonName}": ${error}`);
}
}
// Create a function to update course state on the local server
export function updateCourseStateOnServerLocally(deviceId: string, state: CourseState): Promise<void> {
return new Promise(async (resolve, reject) => {
try {
const creds = await getDeviceCredentials();
if (!creds) {View on GitHub (pinned to 75dd419e61)
Solutions
- List the lesson directory's files and use the exact slug (numeric prefix and `.md` stripped), e.g. `overview` for `02-overview.md`.
- Remove any `.md` extension from stepName before calling.
- Fix typos and casing to match the step file name exactly.
Example fix
// before
await stepContent({ lessonName: 'getting-started', stepName: 'overview.md' });
// after
await stepContent({ lessonName: 'getting-started', stepName: 'overview' }); Defensive patterns
Strategy: validation
Validate before calling
import { readdirSync } from 'node:fs';
import path from 'node:path';
const lessonDir = readdirSync(courseDir).find(d => d.replace(/^\d+-/, '') === lessonName);
const steps = lessonDir
? readdirSync(path.join(courseDir, lessonDir)).filter(f => f.endsWith('.md')).map(f => f.replace(/^\d+-/, '').replace('.md', ''))
: [];
if (!steps.includes(stepName)) {
throw new Error(`Invalid stepName "${stepName}". Available in "${lessonName}": ${steps.join(', ')}`);
}
await stepContent({ lessonName, stepName }); Try / catch
try {
const content = await stepContent({ lessonName, stepName });
} catch (e) {
if (e instanceof Error && e.message.includes('not found in lesson')) {
// surface the valid step names instead of the raw error
} else throw e;
} Prevention
- Never include the `.md` extension in stepName.
- List the lesson's step slugs first and select from them.
- Refresh step lists after any course content update.
When it happens
Trigger: Calling stepContent with a valid lessonName but a stepName that matches no markdown file in that lesson directory — typo, wrong step slug, or step renamed/removed in a newer course version.
Common situations: Agents guessing step names like 'introduction' when the file is 'overview'; users including the `.md` extension in stepName (the code strips it, so 'overview.md' will NOT match 'overview'); outdated course content caches.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Lesson "${lessonName}" not found.
- Not found at ref ${ref}: ${path}
- Template "${slug}" not found. Available templates: ${templat
- ENOENT: no such file or directory: ${path}
- FilesystemSkillsStorage: skill with id ${id} not found
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/33d6f9fd1f416d8d.
Report an issue: GitHub.