Significant-Gravitas/AutoGPT · error · DownloadError
Download failed: ${res.status}
Error message
Download failed: ${res.status} What it means
HTTP 400 from POST /onboarding/step when the submitted step value is not one of the Literal FrontendOnboardingStep values. The endpoint re-validates the step against get_args(FrontendOnboardingStep) even though the request body is typed, because a mismatched payload can bypass static typing at runtime.
Source
Thrown at autogpt_platform/frontend/src/app/(platform)/copilot/components/ArtifactPanel/downloadArtifact.ts:18
import type { ArtifactRef } from "../../store";
const MAX_RETRIES = 2;
const RETRY_DELAY_MS = 500;
function isTransientError(status: number): boolean {
return status >= 500 || status === 408 || status === 429;
}
class DownloadError extends Error {}
async function fetchWithRetry(url: string, retries: number): Promise<Response> {
for (let attempt = 0; attempt <= retries; attempt++) {
try {
const res = await fetch(url);
if (res.ok) return res;
if (!isTransientError(res.status) || attempt === retries) {
throw new DownloadError(`Download failed: ${res.status}`);
}
} catch (error) {
if (error instanceof DownloadError) throw error;
if (attempt === retries) throw error;
}
await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
}
throw new Error("Unreachable");
}
/**
* Trigger a file download from an artifact URL.
*
* Uses fetch+blob instead of a bare `<a download>` because the browser
* ignores the `download` attribute on cross-origin responses (GCS signed
* URLs), and some browsers require the anchor to be attached to the DOM
* before `.click()` fires the download.
*View on GitHub (pinned to 9c8bb5550f)
Solutions
- Send only step values taken from the API's current FrontendOnboardingStep literal set (check the OpenAPI schema for the enum).
- After upgrading the platform, regenerate frontend API types so the step union stays in sync.
- Validate the step client-side against the enum before posting.
Example fix
// before
await api.post('/onboarding/step', { step: 'welcome-tour' });
// after
const STEPS = ['profile-setup', 'agent-template', 'first-agent'] as const; // from generated types
const step = 'profile-setup' satisfies typeof STEPS[number];
await api.post('/onboarding/step', { step }); Defensive patterns
Strategy: type-guard
Validate before calling
const VALID_STEPS = getArgsFromOpenApiSchema(); // values of FrontendOnboardingStep
if (!VALID_STEPS.includes(step)) throw new Error(`Invalid step: ${step}`);
await api.post('/onboarding/step', { step }); Type guard
const isOnboardingStep = (s: string): s is FrontendOnboardingStep => ['profile-setup', 'agent-template'].includes(s); // keep in sync with generated types
Try / catch
const resp = await api.post('/onboarding/step', { step });
if (resp.status === 400) { /* resync step enum from /openapi.json */ } Prevention
- Regenerate frontend types after backend upgrades
- Drive step values from the OpenAPI schema, not hardcoded strings
When it happens
Trigger: Sending {"step": "unknown-step"} or any string outside the Literal set (e.g. an old step name after the enum changed, a typo, or a client built against a newer/older API version).
Common situations: Frontend/backend version skew after onboarding steps were added or renamed; hand-crafted API calls; form submitting before the step constant is set.
Related errors
- Invalid form
- Callback URL origin is not allowed. Allowed origins: {settin
- Unsupported credential type: {request.type}
- Page must be greater than 0
- Page size must be greater than 0
AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14).
Data as JSON: /api/errors/d7fd863eba08c54b.
Report an issue: GitHub.