we-promise/sure · error · ActiveRecord::RecordNotFound

record_not_found

record_not_found

Error message

The requested resource was not found

What it means

Raised by the set_family_export before_action in Api::V1::FamilyExportsController (app/controllers/api/v1/family_exports_controller.rb:85). It fires when params[:id] is not a valid UUID (the guard raises ActiveRecord::RecordNotFound immediately) or when current_resource_owner.family.family_exports.find(:id) matches no row, i.e. the export exists but belongs to another family. The API base maps RecordNotFound to a 404 with error code record_not_found.

Source

Thrown at app/controllers/api/v1/family_exports_controller.rb:85

      }, status: :conflict
      return
    end

    redirect_to rails_blob_url(@family_export.export_file, disposition: "attachment"), allow_other_host: true
  rescue StandardError => e
    Rails.logger.error "FamilyExportsController#download error: #{e.message}"
    Rails.logger.error e.backtrace.join("\n")

    render json: {
      error: "internal_server_error",
      message: "An unexpected error occurred"
    }, status: :internal_server_error
  end

  private

    def set_family_export
      raise ActiveRecord::RecordNotFound unless valid_uuid?(params[:id])

      @family_export = current_resource_owner.family.family_exports.find(params[:id])
    end

    def ensure_read_scope
      authorize_scope!(:read)
    end

    def ensure_write_scope
      authorize_scope!(:write)
    end

    def ensure_admin
      return if current_resource_owner.admin?

      render json: {
        error: "forbidden",
        message: "Family exports require a family admin"

View on GitHub (pinned to e69894adb9)

Solutions

  1. Re-list exports with GET /api/v1/family_exports and use an id from the response
  2. Validate the id is a UUID (8-4-4-4-12 hex) before hitting /:id
  3. Confirm the X-Api-Key belongs to the family that created the export
  4. Treat 404 record_not_found as 'gone': re-create the export instead of retrying the download

Example fix

# before
GET /api/v1/family_exports/0e8d1ceb-5b6d
# after
GET /api/v1/family_exports
GET /api/v1/family_exports/0e8d1ceb-5b6d-4a85-9f2e-74f3b1a2c9d4
Defensive patterns

Strategy: try-catch

Validate before calling

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
UUID_RE.match?(export_id) or raise ArgumentError, 'family_export id must be a UUID'

Try / catch

begin
  resp = client.get("/api/v1/family_exports/#{id}")
rescue Faraday::ResourceNotFound
  # 404 record_not_found: export gone or other family — re-list or re-create
end

Prevention

When it happens

Trigger: GET /api/v1/family_exports/:id (or the download route) with a non-UUID id such as 'latest' or '1'; a well-formed UUID created under a different family; an export deleted (or cleaned up by a retention job) between listing and download; an X-Api-Key whose owner's family simply has no such export.

Common situations: Reusing an export id captured in another environment (staging id against production); expired/purged export files; a truncated or URL-mangled UUID (missing dashes, half-copied); rotating API keys between families.

Related errors


AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21). Data as JSON: /api/errors/8296a6dc4c0e5189. Report an issue: GitHub.