{"record":{"id":"dd8238bc3d1c6eb8","repo":"instructure/canvas-lms","slug":"resource-not-found","errorCode":null,"errorMessage":"resource not found","messagePattern":"resource not found","errorType":"http","errorClass":"Pv4NotFound","httpStatus":404,"severity":"error","filePath":"app/models/page_view/pv4_client.rb","lineNumber":62,"sourceCode":"      start_time ||= Time.at(0).utc\n\n      params = \"start_time=#{start_time.utc.iso8601(PRECISION)}\"\n      params << \"&end_time=#{end_time.utc.iso8601(PRECISION)}\"\n      params << \"&#{cached_root_account_uuids_for(user:)}\"\n      params << \"&last_page_view_id=#{last_page_view_id}\" if last_page_view_id\n      params << \"&limit=#{limit}\" if limit\n      response = CanvasHttp.get(\n        @uri.merge(\"users/#{user.global_id}/page_views?#{params}\").to_s,\n        request_headers\n      )\n\n      case response.code.to_i\n      when 400\n        raise Pv4BadRequest, \"invalid request\"\n      when 401\n        raise Pv4Unauthorized, \"unauthorized request\"\n      when 404\n        raise Pv4NotFound, \"resource not found\"\n      when 429\n        raise Pv4TooManyRequests, \"rate limit exceeded\"\n      end\n\n      json =\n        begin\n          response.body.empty? ? {} : JSON.parse(response.body)\n        rescue JSON::ParserError\n          {}\n        end\n      raise Pv4EmptyResponse, \"the response is empty or does not contain expected keys\" unless json[\"page_views\"]\n\n      json[\"page_views\"].map! do |pv|\n        pv[\"session_id\"] = pv.delete(\"sessionid\")\n        vhost = pv.delete(\"vhost\")\n        http_request = pv.delete(\"http_request\")\n        pv[\"url\"] = if vhost.present? && http_request.present?\n                      \"#{HostUrl.protocol}://#{vhost}#{http_request}\"","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/page_view/pv4_client.rb#L44-L80","documentation":"Pv4Client#fetch raises Pv4NotFound when the PV4 (page views v4) service responds with HTTP 404. It means the requested page-view history resource does not exist on the remote service, e.g. the user has no page-view record set there or the request path/parameters are wrong. This converts a remote HTTP status into a typed Canvas error so callers (via PageView.for_user) can handle it.","triggerScenarios":"Calling PageView.for_user (which calls Pv4Client#fetch) when the PV4 service has no data for the user (404), the user id/timespan query matches nothing, or the PV4 endpoint URL/prefix is misconfigured.","commonSituations":"PV4 not deployed for the user's shard so no records exist; querying history for a brand-new user; environment misconfiguration of the PV4 service host; requests using stale bookmarks pointing at removed data.","solutions":["Verify the user actually has page-view data in PV4 (query the service directly) before expecting results","Check Pv4Client configuration (PV4 host/URL settings) points at the correct service","Confirm the request parameters (user id, oldest/newest) are correct","Handle Pv4NotFound gracefully in the UI (show empty history instead of a hard failure)"],"exampleFix":"// before\nPageView.for_user(user)\n// after\nbegin\n  PageView.for_user(user)\nrescue Pv4NotFound\n  []\nend","handlingStrategy":"try-catch","validationCode":"return [] unless PageView.respond_to?(:for_user) # plus confirm PV4 feature enabled for account\n# check PV4 config is present before calling\nraise ArgumentError, \"PV4 not configured\" unless Pv4Client.new.send(:connection_present?) rescue nil","typeGuard":"def pv4_likely_has_data?(user)\n  user.present? && user.shard.respond_to?(:page_views_enabled?)\nend","tryCatchPattern":"begin\n  views = PageView.for_user(user)\nrescue Pv4NotFound\n  views = []\nend","preventionTips":["Confirm PV4 is enabled/configured for the account before querying history","Handle not-found as an empty result in UI code, never as a 500","Validate user id and date-range parameters before calling","Test against environments where PV4 is and isn't deployed"],"tags":["http","network","pageviews","api"],"backgroundTag":"http-error-response","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}