sipeed/picoclaw · error
Request failed with status ${res.status}
Error message
Request failed with status ${res.status} What it means
This message is the fallback error string produced by readLauncherAuthError in web/frontend/src/api/launcher-auth.ts:74 when POST /api/auth/setup fails and the response body is not JSON containing an error field; it is then re-thrown by handleSave via throw new Error(result.error) at web/frontend/src/components/config/config-page.tsx:684 when result.ok is false. It means the dashboard-password setup endpoint rejected the request with an HTTP error status and no readable error message.
Source
Thrown at web/frontend/src/components/config/config-page.tsx:684
trustedProxyCIDRsText: (
savedLauncherConfig.trusted_proxy_cidrs ?? []
).join("\n"),
dashboardPassword: "",
dashboardPasswordConfirm: "",
}
savedLauncherForm = parsedLauncher
setLauncherForm(parsedLauncher)
setLauncherBaseline(parsedLauncher)
queryClient.setQueryData(
["system", "launcher-config"],
savedLauncherConfig,
)
}
if (launcherPasswordDirty) {
const result = await postLauncherDashboardSetup(password, confirm)
if (!result.ok) {
throw new Error(result.error)
}
const clearedLauncherForm = savedLauncherForm ?? {
...launcherForm,
dashboardPassword: "",
dashboardPasswordConfirm: "",
}
setLauncherForm(clearedLauncherForm)
if (savedLauncherForm) {
setLauncherBaseline(savedLauncherForm)
}
}
if (autoStartDirty) {
if (!autoStartSupported) {
throw new Error(t("pages.config.autostart_unsupported"))
}
const status = await updateAutoStartEnabled(autoStartEnabled)View on GitHub (pinned to 49183d7e8d)
Solutions
- Open the network tab, find POST /api/auth/setup, and read the status code — the message embeds it (e.g. 409)
- For 409: the password is already configured; use the change/update password flow rather than setup
- For 400: choose a stronger password (server-side rules may exceed the client's 8-char minimum) and ensure both fields match
- For 502/HTML responses: fix the reverse proxy routing so /api/auth reaches the launcher backend
Defensive patterns
Strategy: try-catch
Validate before calling
const result = await postLauncherDashboardSetup(password, confirm)
if (!result.ok) {
// result.error may be 'Request failed with status N' when the body had no JSON error
console.warn("setup failed:", result.error)
} Type guard
type SetupResult = { ok: true } | { ok: false; error: string }
function isSetupFailure(r: SetupResult): r is Extract<SetupResult, { ok: false }> {
return !r.ok
} Try / catch
try {
const result = await postLauncherDashboardSetup(password, confirm)
if (isSetupFailure(result)) {
setError(result.error) // includes the HTTP status when the server sent no JSON error
}
} catch (err) {
setError(err instanceof Error ? err.message : "Setup request failed")
} Prevention
- Backend: always return a JSON {error} body on setup failures so the status-only fallback never appears
- Handle 409 explicitly in the UI: setup is one-time, direct users to change-password
- Mirror backend password policy client-side so 400s become pre-validated
When it happens
Trigger: POST /api/auth/setup returns 400 (password too weak/confirmation mismatch server-side), 409 (dashboard password already set — setup is one-time), 401/403 (auth constraints), or a proxy 502 with an HTML body, all without a JSON {error} payload.
Common situations: Trying to 'set' the password again after initial setup instead of using the change-password flow; reverse proxy intercepting /api/auth with an HTML error page; backend version whose setup endpoint validates differently than the frontend (e.g. stricter length); session cookie missing.
Related errors
- Invalid browser login response
- Failed to load config
- Failed to fetch config
- Failed to save config
- Enter and confirm the new login password.
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/2988646bc4e4f2a2.
Report an issue: GitHub.