Freika/dawarich · warning · Error
response.error
Error message
response.error
What it means
A defensive check in SearchManager after LocationSearchService.createVisit resolves. createVisit already throws on any non-OK response, and the success payload is Api::VisitSerializer output (id, name, latitude, ...) with no top-level 'error' key, so this branch is only reachable when the server answers 2xx yet embeds an 'error' field - i.e. an API contract change or an intermediary rewriting responses. In the current codebase it is effectively dead-path defense.
Source
Thrown at app/javascript/maps_maplibre/utils/search_manager.js:646
submitBtn.disabled = true
submitText.classList.add("hidden")
spinner.classList.remove("hidden")
try {
const formData = new FormData(form)
const visitData = {
name: formData.get("name"),
latitude: parseFloat(formData.get("latitude")),
longitude: parseFloat(formData.get("longitude")),
started_at: formData.get("started_at"),
ended_at: formData.get("ended_at"),
status: "confirmed",
}
const response = await this.service.createVisit(visitData)
if (response.error) {
throw new Error(response.error)
}
// Success - close modal and show success message
const modalToggle = modal.querySelector(".modal-toggle")
modalToggle.checked = false
setTimeout(() => modal.remove(), 300)
// Show success notification
this.showSuccessNotification(translate("visits.created_without_name"))
// Dispatch custom event for other components to react
document.dispatchEvent(
new CustomEvent("visit:created", {
detail: {
visit: response,
coordinates: [visitData.longitude, visitData.latitude],
},
}),View on GitHub (pinned to 97fad417c5)
Solutions
- Inspect the actual 200 response body in the Network tab to see what populated response.error
- Confirm the frontend bundle and backend version match (stale cached JS after a deploy is the usual cause)
- If the API genuinely adopted an error-in-200 envelope, update LocationSearchService to detect it centrally instead of per-callsite
- Remove the check or keep it as an assertion if the contract is confirmed to never return error on 2xx
Defensive patterns
Strategy: type-guard
Type guard
/** True when a 2xx body carries an API error envelope. */
function isErroredPayload(payload) {
return (
payload !== null &&
typeof payload === 'object' &&
typeof payload.error === 'string' &&
payload.error.length > 0
)
} Try / catch
try {
const response = await this.service.createVisit(visitData)
if (isErroredPayload(response)) {
throw new Error(response.error)
}
// success path
} catch (error) {
this.showErrorNotification(error.message)
} Prevention
- Centralize envelope checks in the service layer instead of each call site
- Add a response-contract test that asserts the create endpoint never returns error on 2xx
- Treat this branch firing in production as a version-skew signal: check for stale JS bundles after deploys
When it happens
Trigger: A 200 response from /api/v1/visits whose JSON body contains a truthy error key - e.g. after a future API change returning {error: ..., visit: ...}, a proxy injecting an error envelope, or a misrouted request hitting a different endpoint that uses error-style envelopes.
Common situations: API contract drift after upgrading Dawarich while the JS bundle is stale (or vice versa), a debugging middleware that appends error fields to responses, integration tests stubbing fetch with an error envelope and a 200 status.
Related errors
- errorData.error || `Failed to ${isEdit ? "update" : "create"
- Failed to create visit
- name
- latitude
- longitude
AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21).
Data as JSON: /api/errors/a3d2e2b97eeeafd4.
Report an issue: GitHub.