{"record":{"id":"891e3c77adf7a697","repo":"we-promise/sure","slug":"record-not-found-891e3c","errorCode":"record_not_found","errorMessage":"The requested resource was not found","messagePattern":"The requested resource was not found","errorType":"http","errorClass":"ActiveRecord::RecordNotFound","httpStatus":404,"severity":"error","filePath":"app/controllers/api/v1/recurring_transactions_controller.rb","lineNumber":148,"sourceCode":"    Rails.logger.error e.backtrace.join(\"\\n\")\n\n    render json: {\n      error: \"internal_server_error\",\n      message: \"Internal server error\"\n    }, status: :internal_server_error\n  end\n\n  private\n    def set_readable_recurring_transaction\n      @recurring_transaction = find_recurring_transaction(read_recurring_transactions_scope)\n    end\n\n    def set_writable_recurring_transaction\n      @recurring_transaction = find_recurring_transaction(write_recurring_transactions_scope)\n    end\n\n    def find_recurring_transaction(scope)\n      raise ActiveRecord::RecordNotFound unless valid_uuid?(params[:id])\n\n      scope.includes(:account, :merchant).find(params[:id])\n    end\n\n    def ensure_read_scope\n      authorize_scope!(:read)\n    end\n\n    def ensure_write_scope\n      authorize_scope!(:write)\n    end\n\n    def read_recurring_transactions_scope\n      current_resource_owner.family.recurring_transactions.accessible_by(current_resource_owner)\n    end\n\n    def write_recurring_transactions_scope\n      scope = current_resource_owner.family.recurring_transactions","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/controllers/api/v1/recurring_transactions_controller.rb#L130-L166","documentation":"Raised by find_recurring_transaction in Api::V1::RecurringTransactionsController (app/controllers/api/v1/recurring_transactions_controller.rb:143-148). It fires when params[:id] fails the valid_uuid? guard or when the id is not inside the supplied scope (read_recurring_transactions_scope for show, write_recurring_transactions_scope for update/destroy). Both paths produce a 404 record_not_found.","triggerScenarios":"GET/PATCH/DELETE /api/v1/recurring_transactions/:id with a non-UUID id; another family's recurring transaction id; and importantly an id that is readable but not writable — update/destroy use the write scope, so a transaction on an account not writable_by the token owner 404s even though show succeeds.","commonSituations":"Read-only shared account scenarios (spouse's account shared view-only) where a PATCH works in the UI but 404s via API; id copied from a different family or environment; deleted recurring transaction.","solutions":["List with GET /api/v1/recurring_transactions and use an id from the response","For PATCH/DELETE, confirm the underlying account is writable by the token owner (not a view-only shared account)","Validate the id is a UUID before the call","Verify the X-Api-Key family owns the transaction"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"UUID_RE = /\\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\z/i\nUUID_RE.match?(rt_id) or raise ArgumentError, 'recurring_transaction id must be a UUID'","typeGuard":null,"tryCatchPattern":"begin\n  client.patch(\"/api/v1/recurring_transactions/#{id}\", body)\nrescue Faraday::ResourceNotFound\n  # 404: id unknown, other family, or not WRITABLE by this owner (write scope)\nend","preventionTips":["For writes, verify the transaction's account is writable by the token owner","Source ids from GET /api/v1/recurring_transactions","Distinguish 'never existed' from 'read-only' in error reporting"],"tags":["rails","activerecord","record-not-found","http-404","uuid","permissions"],"backgroundTag":"record-not-found","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}