{"record":{"id":"63150474ce1042b0","repo":"Freika/dawarich","slug":"failed-to-create-visit","errorCode":null,"errorMessage":"Failed to create visit","messagePattern":"Failed to create visit","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/javascript/maps_maplibre/services/location_search_service.js","lineNumber":108,"sourceCode":"  }\n\n  /**\n   * Create a new visit\n   * @param {Object} visitData - Visit data\n   * @returns {Promise<Object>} Created visit\n   */\n  async createVisit(visitData) {\n    try {\n      const response = await fetch(\"/api/v1/visits\", {\n        method: \"POST\",\n        headers: this.baseHeaders,\n        body: JSON.stringify({ visit: visitData }),\n      })\n\n      const data = await response.json()\n\n      if (!response.ok) {\n        throw new Error(data.error || data.message || \"Failed to create visit\")\n      }\n\n      return data\n    } catch (error) {\n      console.error(\"LocationSearchService: Create visit error:\", error)\n      throw error\n    }\n  }\n}\n","sourceCodeStart":90,"sourceCodeEnd":118,"githubUrl":"https://github.com/Freika/dawarich/blob/97fad417c5a11b0eb11157890635e015723a2e97/app/javascript/maps_maplibre/services/location_search_service.js#L90-L118","documentation":"LocationSearchService.createVisit POSTs to /api/v1/visits with Bearer auth and throws data.error (set by Api::V1::VisitsController to the Visits::Create service error, e.g. 'Failed to create visit: duplicate visit'), falling back to data.message, then to the generic string. Because response.json() runs before the !response.ok check, a non-JSON body (401 HTML page) actually throws an earlier SyntaxError, not this message - this message fires only for JSON error bodies.","triggerScenarios":"POST /api/v1/visits from the map's 'create visit at location' flow where the visit duplicates an existing one at the same place/time (RecordNotUnique), Place.create! fails validation (blank name, out-of-range coordinates), started_at cannot be parsed, or the endpoint returns a 422 JSON body without error/message keys.","commonSituations":"Clicking 'create visit' twice on the same spot within 100m and same started_at (duplicate visit), expired Bearer key in baseHeaders, user-submitted coordinates outside latitude/longitude bounds, server returning an unexpected JSON envelope after an API version change.","solutions":["Read data.error in the console - it carries the exact Visits::Create failure reason","Check for an existing visit at nearly the same place/time before creating (duplicate visit is the most common 422)","Validate name, latitude, longitude, started_at, ended_at are present and numeric/parseable client-side","Confirm the apiKey given to LocationSearchService is current","Move the response.json() call after the !response.ok check so non-JSON error pages fail with a clear message"],"exampleFix":"// before\nconst data = await response.json()\nif (!response.ok) {\n  throw new Error(data.error || data.message || 'Failed to create visit')\n}\n\n// after\nif (!response.ok) {\n  const data = await response.json().catch(() => ({}))\n  throw new Error(data.error || data.message || `Failed to create visit (HTTP ${response.status})`)\n}\nconst data = await response.json()","handlingStrategy":"try-catch","validationCode":"function isValidVisitData(v) {\n  return (\n    typeof v.name === 'string' && v.name.trim() !== '' &&\n    Number.isFinite(v.latitude) && v.latitude >= -90 && v.latitude <= 90 &&\n    Number.isFinite(v.longitude) && v.longitude >= -180 && v.longitude <= 180 &&\n    !Number.isNaN(Date.parse(v.started_at)) &&\n    !Number.isNaN(Date.parse(v.ended_at))\n  )\n}","typeGuard":null,"tryCatchPattern":"try {\n  const visit = await service.createVisit(visitData)\n  return visit\n} catch (error) {\n  console.error('LocationSearchService: Create visit error:', error)\n  throw error // let the caller decide how to notify the user\n}","preventionTips":["Check the ok status before calling response.json() so non-JSON 401/500 pages fail with a clear message","Validate the duplicate case client-side (same place/time) before POSTing","Keep the console.error in the service but rethrow - swallowing here hides the cause from UI handlers"],"tags":["fetch","api","visits","validation"],"backgroundTag":"api-request-failed","analyzedSha":"97fad417c5a11b0eb11157890635e015723a2e97","analyzedAt":"2026-08-21T17:04:17.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}