{"record":{"id":"74226e61860397b3","repo":"we-promise/sure","slug":"providers-rentcast-errors-no-valuation","errorCode":null,"errorMessage":"providers.rentcast.errors.no_valuation","messagePattern":"providers\\.rentcast\\.errors\\.no_valuation","errorType":"exception","errorClass":"Provider::Rentcast::Error","httpStatus":null,"severity":"warning","filePath":"app/models/provider/rentcast.rb","lineNumber":46,"sourceCode":"    @api_key = api_key # pipelock:ignore\n  end\n\n  # Fetches the value estimate and the subject property's attributes in a\n  # single request — `lookupSubjectAttributes` enriches the AVM response with\n  # the property record, so a separate /v1/properties call isn't needed.\n  def fetch_property_valuation(line1:, locality: nil, region: nil, postal_code: nil)\n    with_provider_response do\n      throttle_request\n      record_monthly_request!\n\n      response = client.get(\"#{base_url}/v1/avm/value\") do |req|\n        req.params[\"address\"] = [ line1, locality, region, postal_code ].map { |part| part.to_s.strip }.reject(&:empty?).join(\", \")\n        req.params[\"lookupSubjectAttributes\"] = true\n      end\n\n      parsed = JSON.parse(response.body)\n      price = parsed[\"price\"]\n      raise Error.new(I18n.t(\"providers.rentcast.errors.no_valuation\")) if price.blank?\n\n      subject = parsed[\"subjectProperty\"] || {}\n\n      PropertyValuation.new(\n        valuation: BigDecimal(price.to_s),\n        currency: \"USD\",\n        property_type: PROPERTY_TYPE_MAP[subject[\"propertyType\"]],\n        year_built: subject[\"yearBuilt\"],\n        area_value: subject[\"squareFootage\"],\n        area_unit: \"sqft\"\n      )\n    end\n  end\n\n  private\n    attr_reader :api_key\n\n    def default_error_transformer(error)","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/rentcast.rb#L28-L64","documentation":"Raised by Provider::Rentcast#fetch_property_valuation when the RentCast AVM endpoint (GET /v1/avm/value) responds 200 but the parsed price field is blank. The message comes from I18n key providers.rentcast.errors.no_valuation (rendered for users, not developers). It means RentCast matched the request but has no valuation model output for that address — a data coverage gap, not an HTTP failure.","triggerScenarios":"Calling fetch_property_valuation with an address RentCast cannot value: outside AVM coverage, rural/non-standard property, new construction not yet in records, or address parts malformed/incomplete enough that no property match yields a price.","commonSituations":"Valuing properties in counties RentCast's AVM doesn't cover; user-entered addresses with typos or missing city/zip; land or unusual property types; brand-new builds with no comps.","solutions":["Verify the address parts (line1, locality, region, postal_code) are complete and correctly spelled","Test the same address directly against RentCast's /v1/avm/value to confirm the coverage gap","Treat as an expected 'no estimate' outcome: rescue and record the property as unvalued rather than failing the batch","For US properties only — RentCast is USD/US-only; non-US addresses will never value"],"exampleFix":"# before\nvaluation = provider.fetch_property_valuation(line1: prop.street) # raises when AVM has no price\n\n# after\nbegin\n  valuation = provider.fetch_property_valuation(\n    line1: prop.street, locality: prop.city, region: prop.state, postal_code: prop.zip\n  )\nrescue Provider::Rentcast::Error => e\n  Rails.logger.info \"No RentCast valuation for #{prop.id}: #{e.message}\"\n  valuation = nil\nend","handlingStrategy":"try-catch","validationCode":"def valuation_address_usable?(line1:, locality:, region:, postal_code:)\n  !line1.to_s.strip.empty? && !locality.to_s.strip.empty? && !region.to_s.strip.empty?\nend\n\nreturn unless valuation_address_usable?(**address)","typeGuard":"def rentcast_no_valuation?(error)\n  error.is_a?(Provider::Rentcast::Error) && error.message == I18n.t(\"providers.rentcast.errors.no_valuation\")\nend","tryCatchPattern":"begin\n  valuation = provider.fetch_property_valuation(**address)\nrescue Provider::Rentcast::Error => e\n  raise unless rentcast_no_valuation?(e)\n  valuation = nil # expected outcome: AVM has no estimate for this address\nend","preventionTips":["Require at least line1 + locality + region before calling the AVM","Normalize user-entered addresses (strip, spell-check USPS) before valuation","Treat 'no valuation' as a data state, not an exception path — log it and move on"],"tags":["rentcast","avm","valuation","no-data","address-matching"],"backgroundTag":"no-results-for-address","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}