{"record":{"id":"a4b02f6bae58e44c","repo":"instructure/canvas-lms","slug":"rubric-not-found-input-id","errorCode":null,"errorMessage":"Rubric not found: #{input[:id]}","messagePattern":"Rubric not found: #(.+?)","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"error","filePath":"app/graphql/mutations/update_rubric_archived_state.rb","lineNumber":30,"sourceCode":"# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more\n# details.\n#\n# You should have received a copy of the GNU Affero General Public License along\n# with this program. If not, see <http://www.gnu.org/licenses/>.\n#\n\nclass Mutations::UpdateRubricArchivedState < Mutations::BaseMutation\n  argument :archived, Boolean, required: true\n  argument :id, ID, required: true\n\n  field :rubric, Types::RubricType, null: true\n  def resolve(input:)\n    begin\n      @rubric = Rubric.find(input[:id])\n    rescue ActiveRecord::RecordNotFound\n      raise GraphQL::ExecutionError, \"Rubric not found: #{input[:id]}\"\n    end\n    requested_permission = input[:archived] ? :archive : :unarchive\n    verify_authorized_action!(@rubric, requested_permission)\n    if input[:archived]\n      @rubric.archive\n    else\n      @rubric.unarchive\n    end\n    { rubric: @rubric }\n  end\nend\n","sourceCodeStart":12,"sourceCodeEnd":42,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/update_rubric_archived_state.rb#L12-L42","documentation":"UpdateRubricArchivedState mutation rescues ActiveRecord::RecordNotFound from Rubric.find and re-raises as a GraphQL::ExecutionError including the offending id. Rubric.find raises RecordNotFound when no rubric with that primary key exists.","triggerScenarios":"Calling updateRubricArchivedState with an id of a deleted rubric, a numeric id that doesn't exist, or an id belonging to another root account/shard.","commonSituations":"UI caching rubric IDs from a removed course; user archiving a rubric that another teacher already deleted; passing a rubric association id instead of the rubric id.","solutions":["Confirm the rubric id exists via a rubric query before mutating","Use the rubric's own id, not the assignment's rubric_association id","Handle the GraphQL error in the client and refresh the rubric list","Check the rubric wasn't deleted or moved to another account"],"exampleFix":"// before\nupdateRubricArchivedState(input: {id: association.rubric_association_id, archived: true})\n// after\nupdateRubricArchivedState(input: {id: association.rubric_id, archived: true})","handlingStrategy":"try-catch","validationCode":"const { rubric } = await gql(rubricQuery, {id}); if (!rubric) skipArchive();","typeGuard":"const isRubric = (r) => r != null && typeof r.id !== 'undefined' && r.__typename === 'Rubric'","tryCatchPattern":"try { await gql(updateRubricArchivedStateMutation, {id, archived}) } catch (e) { if (/Rubric not found/.test(e.message)) { refreshRubricList(); return; } throw e }","preventionTips":["Use rubric_id, not rubric_association_id","Refresh rubric lists after deletions","Confirm same root account/shard"],"tags":["graphql","rubric","record-not-found"],"backgroundTag":"record-not-found","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"}