Freika/dawarich · error · Error
Failed to fetch points: ${response.statusText}
Error message
Failed to fetch points: ${response.statusText} What it means
ApiClient.fetchPoints throws when GET /api/v1/points?start_at&end_at&page&per_page&slim=true&order=asc(&import_id) returns a non-OK status. The message embeds response.statusText, which is frequently an empty string over HTTP/2 and h2c proxies, so the real cause (401 bad Bearer key, 422 invalid date range, 500 server error) is invisible in the message. Pagination headers X-Current-Page / X-Total-Pages are only read on success.
Source
Thrown at app/javascript/maps_maplibre/services/api_client.js:35
async fetchPoints({ start_at, end_at, page = 1, per_page = 1000, signal }) {
const params = new URLSearchParams({
start_at,
end_at,
page: page.toString(),
per_page: per_page.toString(),
slim: "true",
order: "asc",
})
if (this.importId) params.append("import_id", this.importId)
const response = await fetch(`${this.baseURL}/points?${params}`, {
headers: this.getHeaders(),
signal,
})
if (!response.ok) {
throw new Error(`Failed to fetch points: ${response.statusText}`)
}
const points = await response.json()
return {
points,
currentPage: parseInt(response.headers.get("X-Current-Page") || "1", 10),
totalPages: parseInt(response.headers.get("X-Total-Pages") || "1", 10),
totalPointsInRange: parseInt(
response.headers.get("X-Total-Points-In-Range") || "0",
10,
),
scopedPoints: parseInt(
response.headers.get("X-Scoped-Points") || "0",
10,
),
}
}View on GitHub (pinned to 97fad417c5)
Solutions
- Log response.status alongside statusText (HTTP/2 makes statusText empty) to identify 401 vs 422 vs 500
- Verify the api key passed to new ApiClient(apiKey, importId) is the user's current key
- Confirm start_at/end_at are sent and ISO-formatted before the fetch
- If importId is set, check the import still exists and belongs to the current user
- Wrap fetchPoints callers in try/catch and keep the map in a recoverable 'load failed' state instead of a blank canvas
Example fix
// before
if (!response.ok) {
throw new Error(`Failed to fetch points: ${response.statusText}`)
}
// after
if (!response.ok) {
throw new Error(
`Failed to fetch points: ${response.status} ${response.statusText}`.trim(),
)
} Defensive patterns
Strategy: try-catch
Validate before calling
function assertFetchPointsArgs({ start_at, end_at, apiKey }) {
if (!apiKey) throw new Error('API key is required')
const s = Date.parse(start_at)
const e = Date.parse(end_at)
if (Number.isNaN(s) || Number.isNaN(e)) throw new Error('start_at/end_at must be valid dates')
if (s > e) throw new Error('start_at must be before end_at')
} Try / catch
try {
const result = await client.fetchPoints({ start_at, end_at, page, signal })
} catch (error) {
console.error(`fetchPoints failed on page ${page}:`, error.message)
renderMapErrorState() // keep the map usable instead of a blank canvas
} Prevention
- Log response.status, not statusText - HTTP/2 leaves statusText empty
- Pass an AbortController signal so stale paginated requests cancel cleanly on date-range changes
- Surface a retry affordance in the UI for transient 5xx instead of silently dropping later pages
When it happens
Trigger: Maps V2 initial load or date-range change with an invalid/expired apiKey passed to the ApiClient constructor (401), missing or non-ISO start_at/end_at (422), an import_id scoping to a deleted import, or a 500 from the points endpoint. Also thrown when the user's session ends mid-pagination while fetching subsequent pages.
Common situations: Rotated or blank API key in the map element's data attribute, date pickers emitting local-time strings the backend cannot parse, stale import_id kept in page state after re-importing data, server-side timeout on huge date ranges, HTTP/2 deployment stripping statusText so the toast shows just 'Failed to fetch points: '.
Related errors
- errorData.error || `Failed to ${isEdit ? "update" : "create"
- Failed to create visit
- response.error
- Failed to load poster theme "${key}" (${response.status})
- name
AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21).
Data as JSON: /api/errors/f112854d76f14b3f.
Report an issue: GitHub.