instructure/canvas-lms · error · GraphQL::ExecutionError
Invalid context type
Error message
Invalid context type
What it means
Raised in SetFriendlyDescriptionMutation#get_context when the supplied context_type string is not in VALID_CONTEXTS (the whitelist of context classes the mutation supports, e.g. Course/Account). The mutation rejects the request before even attempting to load a record, because constantize on arbitrary strings would be unsafe.
Solutions
- Pass exactly one of the whitelisted context types (check VALID_CONTEXTS in app/graphql/mutations/set_friendly_description.rb — 'Course' or 'Account') with correct capitalization
- Normalize the caller's context type string (e.g. 'course'.capitalize) before sending the mutation
- If the object is a Section/Group/User, find the owning Course or Account and use that as the context instead
- If a new context type is legitimately needed, add it to VALID_CONTEXTS and redeploy (server-side change)
Example fix
// before: raw polymorphic string
const [type, id] = assetString.split('_');
setFriendlyDescription(input: { contextType: type, contextId: id, ... }) // 'course' -> Invalid context type
// after: normalize and whitelist
const CONTEXT_TYPES = ['Course', 'Account'];
const type = assetString.split('_')[0].capitalize;
if (!CONTEXT_TYPES.includes(type)) throw new Error(`unsupported context type: ${type}`);
setFriendlyDescription(input: { contextType: type, contextId: id, ... }); Defensive patterns
Strategy: validation
Validate before calling
const VALID_CONTEXTS = ['Course', 'Account'];
function normalizeContextType(assetStringOrType) {
const raw = assetStringOrType.includes('_')
? assetStringOrType.split('_')[0]
: assetStringOrType;
const type = raw.charAt(0).toUpperCase() + raw.slice(1).toLowerCase();
if (!VALID_CONTEXTS.includes(type)) {
throw new Error(`Unsupported context type: ${raw}. Use Course or Account.`);
}
return type;
} Type guard
const isValidContextType = (t) => typeof t === 'string' && ['Course', 'Account'].includes(t);
Try / catch
try {
await setFriendlyDescription({ variables: { contextType, contextId, outcomeId, description } });
} catch (e) {
if (e.message === 'Invalid context type') {
console.error(`Bad contextType '${contextType}'; expected Course or Account`);
} else { throw e; }
} Prevention
- Normalize asset strings ('course_42') to 'Course' before calling the mutation
- Use a shared constant/enum for context types instead of ad-hoc strings
- Never pass lowercase, pluralized, or unlisted types like 'Section' or 'User' — find the owning Course/Account
- Add a unit test for every contextType value your integration can emit
When it happens
Trigger: Calling setFriendlyDescription with contextType values that are not whitelisted, e.g. lowercase 'course', 'Section', 'User', 'Group', or any other class name outside VALID_CONTEXTS.
Common situations: Frontend deriving context type from a polymorphic asset string like 'course_123' and passing the raw lowercase segment; new integration code guessing context types; typos ('Couse', 'Courses'); using valid Canvas contexts (sections, groups) the mutation simply does not support.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Auto-grading failed due to the following issue(s): #
- cannot import a root group
- invalid context type
- Invalid section ids
- Outcome is not available in context #
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/3c1d653bc364cdc3.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/set_friendly_description.rb:88
private
def validate!(context, outcome)
verify_authorized_action!(context, :manage_outcomes)
unless context.available_outcome(outcome.id, allow_global: true)
raise GraphQL::ExecutionError, I18n.t(
"Outcome %{outcome_id} is not available in context %{context_type}#%{context_id}",
outcome_id: outcome.id.to_s,
context_id: context.id.to_s,
context_type: context.class.name
)
end
end
def get_context(context_type, context_id)
unless VALID_CONTEXTS.include?(context_type)
raise GraphQL::ExecutionError, I18n.t("Invalid context type")
end
context_type.constantize.find_by(id: context_id).tap do |context|
unless context
raise GraphQL::ExecutionError, I18n.t(
"No such context for %{context_type}#%{context_id}",
context_type:,
context_id: context_id.to_s
)
end
end
end
def get_outcome(outcome_id)
LearningOutcome.active.find_by(id: outcome_id).tap do |outcome|
unless outcome
raise GraphQL::ExecutionError, I18n.t(
"No such outcome for id %{id}", { id: outcome_id }View on GitHub (pinned to 1c9f0bb801)