{"record":{"id":"4469c6913a5b344a","repo":"instructure/canvas-lms","slug":"targetcontextid-required-if-targetcontexttype-provided","errorCode":null,"errorMessage":"targetContextId required if targetContextType provided","messagePattern":"targetContextId required if targetContextType provided","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"error","filePath":"app/graphql/mutations/import_outcomes.rb","lineNumber":328,"sourceCode":"      target_group = LearningOutcomeGroup.active.find_by(id: input[:target_group_id])\n      if target_group.nil?\n        raise GraphQL::ExecutionError, I18n.t(\"no such target group\")\n      end\n\n      target_context = target_group.context\n\n      [target_context, target_group]\n    else\n      if input[:target_context_type].blank? && input[:target_context_id].blank?\n        raise GraphQL::ExecutionError, I18n.t(\n          \"You must provide targetGroupId or targetContextId and targetContextType\"\n        )\n      elsif input[:target_context_type].blank? && input[:target_context_id].present?\n        raise GraphQL::ExecutionError, I18n.t(\n          \"targetContextType required if targetContextId provided\"\n        )\n      elsif input[:target_context_type].present? && input[:target_context_id].blank?\n        raise GraphQL::ExecutionError, I18n.t(\n          \"targetContextId required if targetContextType provided\"\n        )\n      end\n\n      target_context =\n        begin\n          context_class(input[:target_context_type]).find_by(\n            id: input[:target_context_id]\n          )\n        rescue NameError\n          raise GraphQL::ExecutionError, I18n.t(\"Invalid targetContextType\")\n        end\n\n      if target_context.nil?\n        raise GraphQL::ExecutionError, I18n.t(\"no such target context\")\n      end\n\n      [target_context, target_context.root_outcome_group]","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/import_outcomes.rb#L310-L346","documentation":"The mirror case of error 210 in ImportOutcomes#get_target: targetContextType is given without targetContextId, so the mutation cannot locate a concrete context. It raises this ExecutionError to enforce that the type and ID are always provided together.","triggerScenarios":"Calling importOutcomes with input { targetContextType: \"Account\" } but blank targetContextId.","commonSituations":"Hardcoded type constants in clients while the ID variable resolves to null/empty; UI state where a type selection persists but the entity was cleared; copy-paste mutations missing the ID field.","solutions":["Include a valid targetContextId matching the given targetContextType","Remove targetContextType entirely and use targetGroupId if no target context is needed","Add client-side validation requiring both fields be set or both be blank"],"exampleFix":"// before\ninput: { targetContextType: \"Account\" }\n// after\ninput: { targetContextType: \"Account\", targetContextId: 7 }","handlingStrategy":"validation","validationCode":"if (input.targetContextType && !input.targetContextId) {\n  throw new Error('targetContextId is required when targetContextType is provided');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await client.mutate({ mutation: IMPORT_OUTCOMES, variables: { input } });\n} catch (e) {\n  if (e.message.includes('targetContextId required')) {\n    // require selecting the target entity before submit\n  }\n}","preventionTips":["Disable the submit button until both type and id are set (or both cleared)","Clear type selection when the entity picker is emptied","Validate pair-completeness in a shared form validator"],"tags":["graphql","validation","outcomes","missing-field"],"backgroundTag":"missing-required-argument","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"}