{"record":{"id":"a3d2e2b97eeeafd4","repo":"Freika/dawarich","slug":"response-error","errorCode":null,"errorMessage":"response.error","messagePattern":"response\\.error","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"app/javascript/maps_maplibre/utils/search_manager.js","lineNumber":646,"sourceCode":"    submitBtn.disabled = true\n    submitText.classList.add(\"hidden\")\n    spinner.classList.remove(\"hidden\")\n\n    try {\n      const formData = new FormData(form)\n      const visitData = {\n        name: formData.get(\"name\"),\n        latitude: parseFloat(formData.get(\"latitude\")),\n        longitude: parseFloat(formData.get(\"longitude\")),\n        started_at: formData.get(\"started_at\"),\n        ended_at: formData.get(\"ended_at\"),\n        status: \"confirmed\",\n      }\n\n      const response = await this.service.createVisit(visitData)\n\n      if (response.error) {\n        throw new Error(response.error)\n      }\n\n      // Success - close modal and show success message\n      const modalToggle = modal.querySelector(\".modal-toggle\")\n      modalToggle.checked = false\n      setTimeout(() => modal.remove(), 300)\n\n      // Show success notification\n      this.showSuccessNotification(translate(\"visits.created_without_name\"))\n\n      // Dispatch custom event for other components to react\n      document.dispatchEvent(\n        new CustomEvent(\"visit:created\", {\n          detail: {\n            visit: response,\n            coordinates: [visitData.longitude, visitData.latitude],\n          },\n        }),","sourceCodeStart":628,"sourceCodeEnd":664,"githubUrl":"https://github.com/Freika/dawarich/blob/97fad417c5a11b0eb11157890635e015723a2e97/app/javascript/maps_maplibre/utils/search_manager.js#L628-L664","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"/** True when a 2xx body carries an API error envelope. */\nfunction isErroredPayload(payload) {\n  return (\n    payload !== null &&\n    typeof payload === 'object' &&\n    typeof payload.error === 'string' &&\n    payload.error.length > 0\n  )\n}","tryCatchPattern":"try {\n  const response = await this.service.createVisit(visitData)\n  if (isErroredPayload(response)) {\n    throw new Error(response.error)\n  }\n  // success path\n} catch (error) {\n  this.showErrorNotification(error.message)\n}","preventionTips":["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"],"tags":["api","defensive-check","visits","search-manager"],"backgroundTag":"api-error-envelope","analyzedSha":"97fad417c5a11b0eb11157890635e015723a2e97","analyzedAt":"2026-08-21T17:04:17.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}