{"record":{"id":"59e787a0b6c82003","repo":"mastra-ai/mastra","slug":"device-credentials-not-found","errorCode":null,"errorMessage":"Device credentials not found.","messagePattern":"Device credentials not found\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mcp-docs-server/src/tools/course.ts","lineNumber":267,"sourceCode":"          }\n        });\n      });\n      req.on('error', error => {\n        reject(error);\n      });\n      req.write(data);\n      req.end();\n    } catch (err) {\n      reject(err);\n    }\n  });\n}\n\n// Create a function to update course state on the server\nasync function updateCourseStateOnServer(deviceId: string, state: CourseState): Promise<void> {\n  const creds = await getDeviceCredentials();\n  if (!creds) {\n    throw new Error('Device credentials not found.');\n  }\n\n  const response = await fetch('https://mastra.ai/api/course/update', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n      'x-mastra-course-key': creds.key,\n    },\n    body: JSON.stringify({\n      id: creds.deviceId,\n      state: state,\n    }),\n  });\n\n  if (!response.ok) {\n    throw new Error(`Course state update failed with status ${response.status}: ${response.statusText}`);\n  }\n}","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/mcp-docs-server/src/tools/course.ts#L249-L285","documentation":"updateCourseStateOnServer syncs course progress to mastra.ai and requires device credentials obtained via getDeviceCredentials(). If those credentials are missing (null), it throws 'Device credentials not found.' — the device has not been registered, so there is no device ID/key to authenticate the sync.","triggerScenarios":"Calling saveCourseState (via startMastraCourse, startMastraCourseLesson, nextMastraCourseStep) when the local device credentials store is empty — the user never completed registration/device pairing.","commonSituations":"Fresh machines or CI containers with no ~/.cache/mastra credentials; credentials file deleted; running the course tools before any registration step.","solutions":["Register the device / complete the course registration flow so getDeviceCredentials() returns credentials.","Verify the credentials file in ~/.cache/mastra (course state dir) exists and is readable.","If registration is not desired, avoid calling the state-saving course tools and use read-only course tools instead."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const creds = await getDeviceCredentials();\nif (!creds) {\n  // register the device before attempting any course state sync\n  await registerDevice();\n}\nawait saveCourseState(state, creds?.deviceId ?? null);","typeGuard":"function hasDeviceCredentials(c: unknown): c is { deviceId: string } {\n  return typeof c === 'object' && c !== null && typeof (c as { deviceId?: unknown }).deviceId === 'string' && (c as { deviceId: string }).deviceId.length > 0;\n}","tryCatchPattern":"try {\n  await saveCourseState(state, deviceId);\n} catch (e) {\n  if (e instanceof Error && e.message === 'Device credentials not found.') {\n    // trigger device registration flow\n  } else throw e;\n}","preventionTips":["Check getDeviceCredentials() before any state-mutating course tool call.","Complete device registration as part of environment setup.","In CI/containers, provision credentials explicitly or skip state-syncing tools."],"tags":["auth","credentials","not-found"],"backgroundTag":"missing-credentials","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}