{"record":{"id":"333e9f86c3ab70fb","repo":"mastra-ai/mastra","slug":"failed-to-read-step-stepname-in-lesson-les","errorCode":null,"errorMessage":"Failed to read step \"${stepName}\" in lesson \"${lessonName}\": ${error}","messagePattern":"Failed to read step \"(.+?)\" in lesson \"(.+?)\": (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mcp-docs-server/src/tools/course.ts","lineNumber":208,"sourceCode":"    throw new Error(`Lesson \"${lessonName}\" not found.`);\n  }\n\n  // Find the step file that matches the name\n  const lessonPath = path.join(courseDir, lessonDir);\n  const files = await fs.readdir(lessonPath);\n  const stepFile = files.find(f => f.endsWith('.md') && f.replace(/^\\d+-/, '').replace('.md', '') === stepName);\n\n  if (!stepFile) {\n    throw new Error(`Step \"${stepName}\" not found in lesson \"${lessonName}\".`);\n  }\n\n  const filePath = path.join(courseDir, lessonDir, stepFile);\n\n  try {\n    const content = await fs.readFile(filePath, 'utf-8');\n    return wrapContentInPrompt(content);\n  } catch (error) {\n    throw new Error(`Failed to read step \"${stepName}\" in lesson \"${lessonName}\": ${error}`);\n  }\n}\n\n// Create a function to update course state on the local server\nexport function updateCourseStateOnServerLocally(deviceId: string, state: CourseState): Promise<void> {\n  return new Promise(async (resolve, reject) => {\n    try {\n      const creds = await getDeviceCredentials();\n      if (!creds) {\n        return reject(new Error('Device credentials not found.'));\n      }\n      const data = JSON.stringify({\n        id: creds.deviceId,\n        state: state,\n      });\n      const options = {\n        hostname: 'localhost',\n        port: 3000,","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/mcp-docs-server/src/tools/course.ts#L190-L226","documentation":"The step file was found, but fs.readFile failed when reading it from disk. The library wraps the underlying Node error (permissions, file removed between listing and read, encoding issues) in this message.","triggerScenarios":"fs.readFile(filePath, 'utf-8') rejects: file deleted/moved after readdir (race with course content update), insufficient read permissions, or I/O errors on the course directory.","commonSituations":"Partial/corrupted installation of the mcp-docs-server package where the course markdown files are missing or unreadable; running as a user without access to the package's files; course content changed mid-request.","solutions":["Reinstall or repair the @mastra/mcp-docs-server package so course markdown files exist and are readable.","Check filesystem permissions on the course content directory and files (chmod/chown).","Retry the request if it was a transient race with a content update."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import { accessSync, constants } from 'node:fs';\naccessSync(filePath, constants.R_OK); // throws early if the file is not readable","typeGuard":null,"tryCatchPattern":"try {\n  const content = await stepContent({ lessonName, stepName });\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Failed to read step')) {\n    // check permissions / reinstall course content, optionally retry once\n  } else throw e;\n}","preventionTips":["Verify package integrity after installing/updating the docs server.","Run with a user that can read the package's course content files.","Retry once on transient EBUSY/ESTALE-style read failures."],"tags":["filesystem","io","read-error"],"backgroundTag":"file-read-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}