{"record":{"id":"0e554f55e81d642a","repo":"Freika/dawarich","slug":"force-re-run-is-not-available-for-paid-geocoding-p","errorCode":null,"errorMessage":"Force re-run is not available for paid geocoding providers on hosted instances.","messagePattern":"Force re-run is not available for paid geocoding providers on hosted instances\\.","errorType":"exception","errorClass":"Jobs::Create::PaidProviderForceRerunBlocked","httpStatus":null,"severity":"error","filePath":"app/services/jobs/create.rb","lineNumber":83,"sourceCode":"    ids\n  end\n\n  # Cloud users share the operator's geocoding budget, so a click that\n  # force-reruns reverse geocoding on a paid provider could fan out to\n  # millions of paid lookups. Self-hosted users own their provider key and\n  # bill — they keep the override.\n  def guard_paid_provider_force_rerun!\n    return unless paid_provider?\n    return if DawarichSettings.self_hosted?\n\n    point_count = user.points.size\n    Rails.logger.warn(\n      \"[Jobs::Create] Refusing to force-rerun reverse geocoding for user=#{user.id} \" \\\n      \"with #{point_count} points: a paid provider (#{paid_provider_name}) is configured \" \\\n      'on a non-self-hosted instance.'\n    )\n\n    raise PaidProviderForceRerunBlocked,\n          'Force re-run is not available for paid geocoding providers on hosted instances.'\n  end\n\n  def paid_provider?\n    DawarichSettings.geoapify_enabled? || DawarichSettings.locationiq_enabled?\n  end\n\n  def paid_provider_name\n    return 'locationiq' if DawarichSettings.locationiq_enabled?\n    return 'geoapify' if DawarichSettings.geoapify_enabled?\n\n    'unknown'\n  end\nend\n","sourceCodeStart":65,"sourceCodeEnd":98,"githubUrl":"https://github.com/Freika/dawarich/blob/97fad417c5a11b0eb11157890635e015723a2e97/app/services/jobs/create.rb#L65-L98","documentation":"Jobs::Create raises PaidProviderForceRerunBlocked when a user requests the 'start_reverse_geocoding' job (a force re-run over ALL of the user's points) while a paid geocoding provider (Geoapify or LocationIQ) is enabled AND the instance is not marked self-hosted. This is a cost guard: on Dawarich's hosted offering, a forced full re-geocode would re-bill every point through the paid API, so the service refuses up front (after logging a warning with the user id and point count).","triggerScenarios":"Calling Jobs::Create.new('start_reverse_geocoding', user_id).call (e.g. the settings page's \"Re-run reverse geocoding\" button posting to the jobs endpoint) on an instance where DawarichSettings.self_hosted? is false and DawarichSettings.geoapify_enabled? or locationiq_enabled? is true. The guard runs before any enqueue, so nothing is queued.","commonSituations":"Hosted Dawarich (app.dawarich.app) users with Geoapify/LocationIQ keys configured clicking force re-run; self-hosters whose SELF_HOSTED setting was never set true after migration, so the instance still looks hosted; CI/staging environments copied from hosted config.","solutions":["Use the 'continue_reverse_geocoding' job instead — it only processes points not yet reverse-geocoded (force: false) and is never blocked by this guard.","If this instance really is self-hosted, enable the self-hosted setting in DawarichSettings so the cost guard is bypassed.","If you call Jobs::Create programmatically, rescue Jobs::Create::PaidProviderForceRerunBlocked and surface a friendly message instead of a 500."],"exampleFix":"# before\nJobs::Create.new('start_reverse_geocoding', current_user.id).call\n\n# after\nbegin\n  Jobs::Create.new('start_reverse_geocoding', current_user.id).call\nrescue Jobs::Create::PaidProviderForceRerunBlocked => e\n  Rails.logger.info(\"Blocked: #{e.message}\")\n  # fall back to only geocoding points that were never geocoded\n  Jobs::Create.new('continue_reverse_geocoding', current_user.id).call\nend","handlingStrategy":"try-catch","validationCode":"blocked =\n  job_name == 'start_reverse_geocoding' &&\n  (DawarichSettings.geoapify_enabled? || DawarichSettings.locationiq_enabled?) &&\n  !DawarichSettings.self_hosted?\nreturn if blocked","typeGuard":null,"tryCatchPattern":"begin\n  Jobs::Create.new(job_name, user_id).call\nrescue Jobs::Create::PaidProviderForceRerunBlocked => e\n  # show cost-policy message to user; offer continue_reverse_geocoding instead\nrescue Jobs::Create::InvalidJobName => e\n  # reject unknown job names\nend","preventionTips":["Hide or disable the force re-run control in the UI when a paid provider is enabled on a hosted instance.","Default to 'continue_reverse_geocoding' (force: false) in integrations; reserve force re-runs for self-hosted setups.","Set the self-hosted flag correctly on self-hosted deployments so cost guards do not misfire."],"tags":["ruby","rails","geocoding","cost-guard","feature-policy","sidekiq"],"backgroundTag":"operation-blocked-by-policy","analyzedSha":"97fad417c5a11b0eb11157890635e015723a2e97","analyzedAt":"2026-08-21T17:04:17.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}