prometheus/prometheus · error · Error
body.error || res.statusText
Error message
body.error || res.statusText
What it means
In the mantine-ui TSDB status page, POSTing to /api/v1/admin/tsdb/delete_series failed with a JSON body; the error message is the server's body.error if present, else the statusText. delete_series is the admin API for dropping series and fails on invalid matchers, parse errors, or when admin APIs are disabled.
Source
Thrown at web/ui/mantine-ui/src/pages/TSDBStatusPage.tsx:120
}
if (endTime !== null) {
params.append("end", (endTime / 1000).toString());
}
setDeleting(true);
try {
const res = await fetch(
`${pathPrefix}/${API_PATH}/admin/tsdb/delete_series?${params.toString()}`,
{
method: "POST",
credentials: "same-origin",
}
);
if (!res.ok) {
if (res.headers.get("content-type")?.startsWith("application/json")) {
const body = await res.json();
throw new Error(body.error || res.statusText);
}
throw new Error(res.statusText);
}
setDeleteSuccess(
`Successfully deleted series matching: ${matchList.join(", ")}`
);
setMatchers("");
setStartTime(null);
setEndTime(null);
} catch (err) {
setDeleteError(err instanceof Error ? err.message : "Unknown error");
} finally {
setDeleting(false);
}
};
const handleCleanTombstones = async () => {View on GitHub (pinned to 44d6a0e0b1)
Solutions
- Start Prometheus with --web.enable-admin-api to enable delete_series.
- Fix matcher syntax (must be a valid PromQL selector, e.g. {job="x"}).
- Ensure start/end times fall within existing data and are not equal/empty in invalid ways.
- Read body.error in the shown message for the exact server reason.
Example fix
# before prometheus --config.file=prometheus.yml # after (enable the admin API this page needs) prometheus --config.file=prometheus.yml --web.enable-admin-api
Defensive patterns
Strategy: validation
Validate before calling
function validMatchers(m: string): boolean {
try {
// reuse prometheus regexp/label syntax check, minimally: non-empty, balanced braces
return m.trim().length > 0 && (m.match(/{/g) ?? []).length === (m.match(/}/g) ?? []).length;
} catch {
return false;
}
} Type guard
function isJSONErrorBody(body: unknown): body is { error: string } {
return typeof (body as any)?.error === 'string';
} Try / catch
catch (err) {
if (err instanceof Error) {
setDeleteError(err.message); // body.error carries the exact server reason
if (err.message.includes('admin APIs disabled')) promptEnableAdminApi();
}
} Prevention
- Run Prometheus with --web.enable-admin-api when using the delete UI.
- Validate matcher syntax client-side before POSTing delete_series.
- Ensure start/end times intersect the retained data window.
When it happens
Trigger: Invalid matcher syntax in the match field, start/end outside retained data bounds, or the admin API disabled — the server responds 400/501/503 with {"status":"error","error":"..."}.
Common situations: --web.enable-admin-api not passed to Prometheus (admin APIs off by default); malformed matchers like '{foo' or empty match; timestamps outside the retention window.
Related errors
- res.statusText
- res.statusText
- missing "error" field in response JSON
- Unknown error
- Network error or unable to reach the server
AI-assisted analysis of prometheus/prometheus@44d6a0e0b1 (2026-08-15).
Data as JSON: /api/errors/7903399422129b24.
Report an issue: GitHub.