{"record":{"id":"5bfc1c4f83fabe64","repo":"instructure/canvas-lms","slug":"not-found-update-internal-setting","errorCode":null,"errorMessage":"not found","messagePattern":"not found","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"warning","filePath":"app/graphql/mutations/update_internal_setting.rb","lineNumber":40,"sourceCode":"  argument :internal_setting_id, ID, required: true, prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func(\"InternalSetting\")\n  argument :value, String, required: true\n\n  field :internal_setting, Types::InternalSettingType, null: false\n  def resolve(input:)\n    if !Account.site_admin.grants_right?(current_user, :manage_internal_settings) || (internal_setting = Setting.find(input[:internal_setting_id])).secret\n      raise GraphQL::ExecutionError, \"insufficient permission\"\n    end\n\n    unless input[:value].nil?\n      Setting.set(internal_setting.name, input[:value])\n      internal_setting.reload\n    end\n\n    {\n      internal_setting:\n    }\n  rescue ActiveRecord::RecordNotFound\n    raise GraphQL::ExecutionError, \"not found\"\n  end\nend\n","sourceCodeStart":22,"sourceCodeEnd":43,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/update_internal_setting.rb#L22-L43","documentation":"This is a generic rescue in the UpdateInternalSetting GraphQL mutation: when the lookup of the internal setting record raises ActiveRecord::RecordNotFound, it is converted into a GraphQL::ExecutionError with the unhelpful message \"not found\". Canvas raises it so clients get a normal GraphQL error instead of an unhandled 500.","triggerScenarios":"Calling updateInternalSetting with an `internal_setting` id (or name) that does not match any InternalSetting row in the database.","commonSituations":"Typoed setting name/id; querying a setting that only exists on a different shard or environment; setting deleted before the mutation ran; staging vs production data mismatch.","solutions":["Verify the internal_setting id/name passed in the mutation arguments exists (e.g. InternalSetting.find in console).","Check you are operating on the correct database/shard where the setting lives.","Correct the client input so it references a valid setting id.","If a legitimately missing setting should be a no-op, handle it before calling the mutation instead of relying on the error."],"exampleFix":"// before\nmutation {\n  updateInternalSetting(input: {internalSettingId: \"123\"}) { ... }\n}\n// after\n# resolve by the real setting name/id first:\n# setting = InternalSetting.find_by(name: \"my_setting\")\nmutation {\n  updateInternalSetting(input: {internalSettingId: \"42\"}) { ... }\n}","handlingStrategy":"try-catch","validationCode":"// resolve the setting first\nconst setting = await gql(FETCH_INTERNAL_SETTING, { id });\nif (!setting?.internalSetting) throw new NotFoundError(id);","typeGuard":"function hasInternalSetting(data) { return data?.internalSetting != null; }","tryCatchPattern":"try {\n  await gql(UPDATE_INTERNAL_SETTING, { internalSettingId: id });\n} catch (e) {\n  if (e.message === 'not found') { /* surface 'setting not found' to user */ }\n  else throw e;\n}","preventionTips":["Resolve setting ids/names from a query rather than hardcoding","Check shard/environment before mutating","Handle soft-deleted settings in UI state"],"tags":["graphql","activerecord","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"}