{"record":{"id":"90e27c9d8fd1ecea","repo":"instructure/canvas-lms","slug":"sorting-by-field-is-only-available-within-a-course-context","errorCode":null,"errorMessage":"Sorting by #{field} is only available within a course context","messagePattern":"Sorting by #(.+?) is only available within a course context","errorType":"exception","errorClass":"RequestError","httpStatus":400,"severity":"error","filePath":"lib/user_search.rb","lineNumber":475,"sourceCode":"      scope\n    end\n\n    def email_sql(users_scope, params)\n      users_scope.select(\"users.*, MAX(pseudonyms.current_login_at) as last_login\")\n                 .joins(:communication_channels)\n                 .joins(\"LEFT JOIN #{Pseudonym.quoted_table_name} ON pseudonyms.user_id = users.id\n          AND pseudonyms.account_id = #{User.connection.quote(params[:account].id_for_database)}\n          #{\"AND pseudonyms.workflow_state = 'active'\" unless @include_deleted_users}\")\n                 .where(communication_channels: { workflow_state: [\"active\", \"unconfirmed\"], path_type: params[:path_type] })\n                 .where(like_condition(\"communication_channels.path\"), pattern: params[:pattern])\n    end\n\n    def wildcard_pattern(value, **)\n      ActiveRecord::Base.wildcard_pattern(value, **)\n    end\n\n    def raise_context_error(field)\n      raise RequestError.new(\"Sorting by #{field} is only available within a course context\", 400)\n    end\n  end\nend\n","sourceCodeStart":457,"sourceCodeEnd":479,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/user_search.rb#L457-L479","documentation":"UserSearch.raise_context_error in lib/user_search.rb:475 raises RequestError (400) when a sort field is requested in a non-course context. Called by order_scope, it enforces that certain sortable fields only make sense where course-scoped enrollment data exists.","triggerScenarios":"Calling the user search/list API with a sort parameter (e.g. sortable_name/surname style course-only fields) on an account or group context where order_scope detects the context is not a Course.","commonSituations":"Reusing a course users-endpoint client against an account users endpoint with the same sort params; UI code copied from course roster to account user list; generic API wrappers always sending a sort field.","solutions":["Remove the sort parameter when querying users outside a course context","Branch client code on context type and only send sortable fields for courses","Rescue RequestError (400) and retry without the sort field","Use a context-appropriate default ordering for account/group user lists"],"exampleFix":"// before\nGET /api/v1/accounts/1/users?sort=surname\n// after\nGET /api/v1/accounts/1/users # no sort param outside course context","handlingStrategy":"validation","validationCode":"raise RequestError.new('sort not allowed here', 400) unless context.is_a?(Course)","typeGuard":null,"tryCatchPattern":"begin\n  UserSearch.for_user_in_context(term, context, user, session, sort: field)\nrescue RequestError => e\n  retry_without_sort or render json: {error: e.message}, status: 400\nend","preventionTips":["Only send course-only sort params for course contexts","Centralize sort-param handling per context type","Document which sort fields require course scope"],"tags":["ruby","sorting","context","http-400"],"backgroundTag":"invalid-query-parameter","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"}