{"record":{"id":"a1504b3cf1053d8c","repo":"instructure/canvas-lms","slug":"must-specify-exactly-one-of-id-or-sisid","errorCode":null,"errorMessage":"Must specify exactly one of id or sisId","messagePattern":"Must specify exactly one of id or sisId","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"error","filePath":"app/graphql/types/query_type.rb","lineNumber":45,"sourceCode":"    field :legacy_node, GraphQL::Types::Relay::Node, null: true do\n      description \"Fetches an object given its type and legacy ID\"\n      argument :_id, ID, required: true\n      argument :type, LegacyNodeType, required: true\n    end\n    def legacy_node(type:, _id:) # rubocop:disable Lint/UnderscorePrefixedVariableName -- named for DSL reasons\n      GraphQLNodeLoader.load(type, _id, context)\n    end\n\n    field :account, Types::AccountType, null: true do\n      argument :id,\n               ID,\n               \"a graphql or legacy id\",\n               required: false,\n               prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func(\"Account\")\n      argument :sis_id, String, \"a id from the original SIS system\", required: false\n    end\n    def account(id: nil, sis_id: nil)\n      raise GraphQL::ExecutionError, \"Must specify exactly one of id or sisId\" if (id && sis_id) || !(id || sis_id)\n      return GraphQLNodeLoader.load(\"Account\", id, context) if id\n\n      GraphQLNodeLoader.load(\"AccountBySis\", sis_id, context) if sis_id\n    end\n\n    field :user, Types::UserType, null: true do\n      argument :id,\n               ID,\n               \"a graphql or legacy id\",\n               required: true,\n               prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func(\"User\")\n    end\n    def user(id:)\n      GraphQLNodeLoader.load(\"User\", id, context)\n    end\n\n    field :course, Types::CourseType, null: true do\n      argument :id,","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/types/query_type.rb#L27-L63","documentation":"Canvas's GraphQL `account` resolver accepts either a GraphQL/legacy `id` or a SIS `sis_id`, but not both and not neither. It raises this GraphQL::ExecutionError when the argument pair is ambiguous or missing, so the lookup target is unambiguous.","triggerScenarios":"Calling query { account(...) } with both id and sisId supplied, or with neither supplied (or both null). Any other argument combination (exactly one) is accepted.","commonSituations":"Clients templating the query pass both fields as variables with one left as an empty value that still serializes; frontend code copies a query snippet and leaves a stale id variable when switching to sisId lookup; omitting arguments entirely when testing in GraphiQL.","solutions":["Pass exactly one of `id` or `sisId`; remove the other argument from the query/variables.","If both values exist, decide which lookup you need (SIS IDs require SIS import context) and drop the other.","Check variable serialization so unset variables are omitted rather than sent as empty strings/nulls."],"exampleFix":"// before\nquery { account(id: \"1\", sisId: \"acc-100\") { name } }\n// after\nquery { account(sisId: \"acc-100\") { name } }","handlingStrategy":"validation","validationCode":"const argCount = [vars.id, vars.sisId].filter(v => v != null && v !== '').length;\nif (argCount !== 1) throw new Error('account requires exactly one of id or sisId');","typeGuard":"const hasExactlyOne = (vars) => ['id','sisId'].filter(k => vars[k] != null && vars[k] !== '').length === 1;","tryCatchPattern":"try { await gql(ACCOUNT_QUERY, vars); } catch (e) { if (e.message.includes('Must specify exactly one of id or sisId')) { vars = pickSingleIdentifier(vars, ['id','sisId']); retry } else throw e; }","preventionTips":["Use separate query documents for id-lookup vs sisId-lookup instead of one query with both optional arguments.","Strip null/empty-string variables before sending requests.","Document which lookup mode your integration uses and enforce it in a shared request helper."],"tags":["graphql","validation","arguments"],"backgroundTag":"mutually-exclusive-options","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"}