instructure/canvas-lms · error · Pv4NotFound
resource not found
Error message
resource not found
What it means
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.
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)
Example fix
// before PageView.for_user(user) // after begin PageView.for_user(user) rescue Pv4NotFound [] end
Defensive patterns
Strategy: try-catch
Validate before calling
return [] unless PageView.respond_to?(:for_user) # plus confirm PV4 feature enabled for account # check PV4 config is present before calling raise ArgumentError, "PV4 not configured" unless Pv4Client.new.send(:connection_present?) rescue nil
Type guard
def pv4_likely_has_data?(user) user.present? && user.shard.respond_to?(:page_views_enabled?) end
Try / catch
begin views = PageView.for_user(user) rescue Pv4NotFound views = [] end
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- failed to load page view history due to service timeout
- rate limit exceeded
- could not retrieve configuration, the server response timed…
- Couldn't send LTI AGS grade progress metric
- Error retrieving results from Outcomes Service: #
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/dd8238bc3d1c6eb8.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/page_view/pv4_client.rb:62
start_time ||= Time.at(0).utc
params = "start_time=#{start_time.utc.iso8601(PRECISION)}"
params << "&end_time=#{end_time.utc.iso8601(PRECISION)}"
params << "&#{cached_root_account_uuids_for(user:)}"
params << "&last_page_view_id=#{last_page_view_id}" if last_page_view_id
params << "&limit=#{limit}" if limit
response = CanvasHttp.get(
@uri.merge("users/#{user.global_id}/page_views?#{params}").to_s,
request_headers
)
case response.code.to_i
when 400
raise Pv4BadRequest, "invalid request"
when 401
raise Pv4Unauthorized, "unauthorized request"
when 404
raise Pv4NotFound, "resource not found"
when 429
raise Pv4TooManyRequests, "rate limit exceeded"
end
json =
begin
response.body.empty? ? {} : JSON.parse(response.body)
rescue JSON::ParserError
{}
end
raise Pv4EmptyResponse, "the response is empty or does not contain expected keys" unless json["page_views"]
json["page_views"].map! do |pv|
pv["session_id"] = pv.delete("sessionid")
vhost = pv.delete("vhost")
http_request = pv.delete("http_request")
pv["url"] = if vhost.present? && http_request.present?
"#{HostUrl.protocol}://#{vhost}#{http_request}"View on GitHub (pinned to 1c9f0bb801)