{"record":{"id":"69572a17c504f44c","repo":"we-promise/sure","slug":"not-found-69572a","errorCode":"not_found","errorMessage":"Resource not found","messagePattern":"Resource not found","errorType":"exception","errorClass":"Provider::Lunchflow::LunchflowError","httpStatus":404,"severity":"error","filePath":"app/models/provider/lunchflow.rb","lineNumber":133,"sourceCode":"        \"x-api-key\" => api_key,\n        \"Content-Type\" => \"application/json\",\n        \"Accept\" => \"application/json\"\n      }\n    end\n\n    def handle_response(response)\n      case response.code\n      when 200\n        JSON.parse(response.body, symbolize_names: true)\n      when 400\n        Rails.logger.error \"Lunch Flow API: Bad request - #{response.body}\"\n        raise LunchflowError.new(\"Bad request to Lunch Flow API: #{response.body}\", :bad_request)\n      when 401\n        raise LunchflowError.new(\"Invalid API key\", :unauthorized)\n      when 403\n        raise LunchflowError.new(\"Access forbidden - check your API key permissions\", :access_forbidden)\n      when 404\n        raise LunchflowError.new(\"Resource not found\", :not_found)\n      when 429\n        raise LunchflowError.new(\"Rate limit exceeded. Please try again later.\", :rate_limited)\n      else\n        Rails.logger.error \"Lunch Flow API: Unexpected response - Code: #{response.code}, Body: #{response.body}\"\n        raise LunchflowError.new(\"Failed to fetch data: #{response.code} #{response.message} - #{response.body}\", :fetch_failed)\n      end\n    end\n\n    class LunchflowError < StandardError\n      attr_reader :error_type\n\n      def initialize(message, error_type = :unknown)\n        super(message)\n        @error_type = error_type\n      end\n    end\nend\n","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/lunchflow.rb#L115-L151","documentation":"HTTP 404 branch of Provider::Lunchflow#handle_response (app/models/provider/lunchflow.rb:132-133). Thrown as LunchflowError(:not_found) with message 'Resource not found' when Lunchflow returns 404 for any endpoint: the URL's account id does not exist on the server side (path is /accounts/{url_encoded_id}/...), or the base_url does not match the server's route table (e.g. missing or wrong /api/v1 version prefix so every path 404s).","triggerScenarios":"get_account_transactions/balance/holdings called with an account_id deleted at Lunchflow or belonging to a different workspace; ids recorded from a sandbox base_url then used against production; base_url override with a typo'd or missing version segment making all sub-paths unmatched; nil account_id producing '/accounts//transactions'.","commonSituations":"Accounts unlinked and re-linked upstream while local records keep old ids; environment mismatch between recorded ids and configured base_url; provider deprecating an endpoint (e.g. holdings) with 404 instead of 501.","solutions":["Re-list accounts with get_accounts and verify the account_id still exists; retire ids that no longer appear.","If every call 404s (even get_accounts), audit the base_url — it likely has the wrong path/version; it should be https://lunchflow.app/api/v1.","Guard callers to treat :not_found per-account: drop the account from the sync set instead of failing the whole job.","Confirm you are not passing a provider-internal id from another provider."],"exampleFix":"// before\nbegin\n  client.get_account_transactions(acct_id)\nrescue => e\n  raise # aborts the whole sync on one stale account\nend\n\n// after\nbegin\n  client.get_account_transactions(acct_id)\nrescue Provider::Lunchflow::LunchflowError => e\n  raise unless e.error_type == :not_found\n  account.update!(status: 'disconnected') and next_account\nend","handlingStrategy":"fallback","validationCode":"ids = client.get_accounts[:accounts].map { |a| a[:id] }\nacct_ids &= ids # only sync ids that still exist upstream","typeGuard":"def not_found?(e)\n  e.is_a?(Provider::Lunchflow::LunchflowError) && e.error_type == :not_found\nend","tryCatchPattern":"begin\n  client.get_account_balance(acct_id)\nrescue Provider::Lunchflow::LunchflowError => e\n  raise unless e.error_type == :not_found\n  account.mark_deleted_upstream! # skip, keep the rest of the sync running\nend","preventionTips":["Reconcile account ids against get_accounts at sync start.","Keep environment-specific ids separated (staging vs production base_urls).","Fail per-account, never per-job, on 404s."],"tags":["lunchflow","http-404","stale-id","base-url","api"],"backgroundTag":"api-resource-not-found","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}