mastra-ai/mastra · error · Error
Course state update failed with status ${response.status}: $
Error message
Course state update failed with status ${response.status}: ${response.statusText} What it means
The POST to https://mastra.ai/api/course/update returned a non-OK HTTP status. The server rejected the state sync (auth failure, validation error, server error), and the library surfaces the status code and status text.
Source
Thrown at packages/mcp-docs-server/src/tools/course.ts:283
const creds = await getDeviceCredentials();
if (!creds) {
throw new Error('Device credentials not found.');
}
const response = await fetch('https://mastra.ai/api/course/update', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-mastra-course-key': creds.key,
},
body: JSON.stringify({
id: creds.deviceId,
state: state,
}),
});
if (!response.ok) {
throw new Error(`Course state update failed with status ${response.status}: ${response.statusText}`);
}
}
async function saveCourseState(state: CourseState, deviceId: string | null): Promise<void> {
// If no device ID, the user isn't registered - this is an error condition
if (!deviceId) {
throw new Error('Cannot save course state: User is not registered');
}
const statePath = await getCourseStatePath();
try {
// Save to local filesystem
await fs.writeFile(statePath, JSON.stringify(state, null, 2), 'utf-8');
// Sync with server
try {
// Use getDeviceCredentials to ensure we have the key
const creds = await getDeviceCredentials();
if (!creds) throw new Error('Device credentials not found');
await updateCourseStateOnServer(creds.deviceId, state);View on GitHub (pinned to 75dd419e61)
Solutions
- Check the HTTP status: 401/403 → re-register the device to get fresh credentials; 5xx → retry later.
- Verify network/proxy access to mastra.ai from the machine.
- Note that the local save may still have succeeded — check local state before assuming data loss, then retry the sync.
Defensive patterns
Strategy: retry
Validate before calling
const res = await fetch('https://mastra.ai/api/course/update', { method: 'HEAD' }).catch(() => null);
if (!res || !res.ok) {
// mastra.ai unreachable or degraded — defer sync instead of calling saveCourseState
} Try / catch
try {
await saveCourseState(state, deviceId);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Course state update failed with status')) {
const status = Number(e.message.match(/status (\d+)/)?.[1]);
if (status >= 500 || status === 429) { /* retry with backoff */ }
else if (status === 401 || status === 403) { /* re-register device */ }
} else throw e;
} Prevention
- Retry 5xx/429 responses with exponential backoff; re-authenticate on 401/403.
- Keep local state as the source of truth; treat server sync as best-effort.
- Monitor mastra.ai status before bulk sync operations.
When it happens
Trigger: fetch('https://mastra.ai/api/course/update') responds with 4xx/5xx: invalid or expired device credentials, malformed state payload, network-level proxy interception, or mastra.ai API outage.
Common situations: Expired/revoked device ID; corporate proxy returning 403/502; mastra.ai API downtime; course state schema changed server-side after a client update.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Perplexity Search request failed with status ${response.stat
- Failed to fetch Copilot models: ${response.status} ${respons
- Failed to list projects (${res.status})
- Failed to create project (${res.status})
- Failed to create access token (${res.status})
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/5094579d3f0e095a.
Report an issue: GitHub.