instructure/canvas-lms · error · ArgumentError
quiz_submission not found in connection items
Error message
quiz_submission not found in connection items
What it means
PatchedArrayConnection computes quiz submission cursors using object identity (equal?) rather than id equality, because all versions of a quiz_submission in submission history share the same id but represent different attempts. If the node is not the exact in-memory object contained in items, this ArgumentError is raised.
Solutions
- Use the exact object instance from the connection's items array when requesting the cursor
- Re-fetch the whole connection (nodes + page info) in a single request instead of mixing objects
- Avoid re-loading the quiz submission by id; keep a reference to the original item
- If building custom nodes, insert them into the connection so identity holds
Example fix
// before const qs = QuizSubmission.find(id) const cursor = connection.cursorFor(qs) // new object, identity check fails // after const qs = connection.items.find(i => i.id === id) const cursor = connection.cursorFor(qs)
Defensive patterns
Strategy: validation
Validate before calling
const inPage = connection.items.includes(node) // identity check, same as resolver
if (!inPage) throw new Error('quiz submission object not in this page') Try / catch
try {
const cursor = connection.cursorFor(node)
} catch (e) {
if (/quiz_submission not found in connection items/.test(e.message)) {
node = connection.items.find(i => i.id === node.id) // re-acquire exact instance
} else throw e
} Prevention
- Keep references to objects returned by the connection; do not re-find by id
- Fetch nodes and page info in one request
- Remember cursor matching is object identity, not id equality
When it happens
Trigger: Requesting a cursor for a QuizSubmission object that is a different Ruby object instance than the one in items — a re-fetched copy, a deserialized version from simply_versioned, or a node loaded outside this connection's items array.
Common situations: Passing a freshly loaded QuizSubmission.find(id) instead of the object from the connection items; mixing objects across shards/requests; constructing quiz submission history nodes manually and then asking this connection for their cursors.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- submission not found in connection items
- Cannot request more than 100 courses at once
- relative entry not found
- and cannot be used together
- and cannot be used together
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/237d928db8bee1c4.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/patched_array_connection.rb:41
# the index. Unfortunately submission histories are saved through versionable
# which returns an array of submission histories that all share the same id,
# and active record overrides the `==` method to check for equality based on
# said id. When dealing with submissions, change the comparator to look at the
# submitted_at time (what submission#submission_history is doing) instead of
# by id so cursors don't break.
def cursor_for_submission_node(submission)
submission_idx = items.find_index { |i| i.submitted_at.to_i == submission.submitted_at.to_i }
raise ArgumentError, "submission not found in connection items" unless submission_idx
encode((submission_idx + 1).to_s)
end
def cursor_for_quiz_submission_node(quiz_submission)
# Use object identity (not AR `==` which compares by id) since all items
# in the array share the same quiz_submission id but represent different
# attempts via simply_versioned deserialization.
quiz_submission_idx = items.find_index { |i| i.equal?(quiz_submission) }
raise ArgumentError, "quiz_submission not found in connection items" unless quiz_submission_idx
encode((quiz_submission_idx + 1).to_s)
end
def cursor_for(item)
return cursor_for_submission_node(item) if item.instance_of?(Submission)
return cursor_for_quiz_submission_node(item) if item.instance_of?(Quizzes::QuizSubmission)
super
end
end
View on GitHub (pinned to 1c9f0bb801)