mastra-ai/mastra · error
Request failed (${res.status}) / server-provided message
Error message
Request failed (${res.status}) / server-provided message What it means
requestIntakeConfig is the shared fetch helper for the intake config API, used by fetchIntakeConfig and saveIntakeConfig. On a non-OK response it throws an Error preferring the server body's message then error field, falling back to 'Request failed (<status>)'. On success it normalizes the returned config into IntakeSelection records.
Source
Thrown at mastracode/factory-ui/src/ui/domains/factory/services/intake.ts:58
return selection.enabled ? selection : { ...selection, enabled: true };
}
async function requestIntakeConfig(baseUrl: string, init?: RequestInit): Promise<IntakeConfig> {
const res = await fetch(`${baseUrl}/web/intake/config`, {
headers: { Accept: 'application/json', ...(init?.body ? { 'content-type': 'application/json' } : {}) },
credentials: 'include',
...init,
});
if (!res.ok) {
let message = `Request failed (${res.status})`;
try {
const body = (await res.json()) as { error?: string; message?: string };
if (body.message) message = body.message;
else if (body.error) message = body.error;
} catch {
/* ignore non-JSON */
}
throw new Error(message);
}
const { config } = (await res.json()) as { config?: Partial<Record<string, IntakeSelection>> };
return normalizeIntakeConfig(config);
}
/** Read the caller's intake config (server falls back to the defaults). */
export async function fetchIntakeConfig(baseUrl: string): Promise<IntakeConfig> {
return requestIntakeConfig(baseUrl);
}
/** Save the caller's intake config; resolves to the persisted config. */
export async function saveIntakeConfig(baseUrl: string, config: IntakeConfig): Promise<IntakeConfig> {
return requestIntakeConfig(baseUrl, { method: 'PUT', body: JSON.stringify(config) });
}
/** Routing of one intake source to the Factory project its items land in. */
export interface IntakeSourceBinding {
integrationId: string;View on GitHub (pinned to 75dd419e61)
Solutions
- Read error.message for the server-provided cause; otherwise use the status code
- Re-authenticate if the status is 401/403
- For saves, validate intake selection keys/values against the current IntakeSelection schema before calling saveIntakeConfig
- If 5xx, retry after the backend is healthy
Example fix
// before
await saveIntakeConfig(baseUrl, { legacyField: { id: 'x' } } as Record<string, IntakeSelection>);
// after
const cfg = normalizeIntakeConfig({ area: { id: 'x' } });
await saveIntakeConfig(baseUrl, cfg); Defensive patterns
Strategy: validation
Validate before calling
function isValidIntakeConfig(cfg: unknown): cfg is Record<string, IntakeSelection> {
if (typeof cfg !== 'object' || cfg === null) return false;
return Object.values(cfg).every(v => typeof v === 'object' && v !== null && typeof (v as { id?: unknown }).id === 'string');
}
if (!isValidIntakeConfig(draftConfig)) throw new Error('Intake selections must map keys to { id: string }'); Type guard
function isIntakeSelection(v: unknown): v is IntakeSelection {
return typeof v === 'object' && v !== null && typeof (v as { id?: unknown }).id === 'string';
} Try / catch
try {
await saveIntakeConfig(baseUrl, config);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
if (/401|403/.test(msg)) promptLogin();
else if (/400/.test(msg)) showValidationBanner(msg);
else showRetryOption(msg);
} Prevention
- Normalize drafts with normalizeIntakeConfig before saving
- Run normalizeIntakeConfig on all fetched configs so stale server data cannot poison the UI
- Re-check session validity before writes (401s are most common on save)
- Keep the IntakeSelection type as the single shared contract between client and server
When it happens
Trigger: Any non-OK res.status from GET (fetchIntakeConfig) or save (saveIntakeConfig) of the intake config: 401 unauthenticated, 403 forbidden for the target user/scope, 400 when saved selections fail server validation, or 5xx backend errors.
Common situations: Session cookie expired before saving intake config, submitting intake selections containing keys/values the server rejects after a schema change, another user's config requested without permission, or the intake service returning 502 during deploy.
Related errors
- Perplexity Search request failed with status ${response.stat
- Request failed (${response.status}) / server-provided messag
- Request failed (${res.status}) / server-provided message
- Failed to load pull request subscriptions (${response.status
- Failed to fetch Copilot models: ${response.status} ${respons
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/54c9af52b8b45ff0.
Report an issue: GitHub.