instructure/canvas-lms · error · GraphQL::ExecutionError
Unable to find OutcomeProficiency
Error message
Unable to find OutcomeProficiency
What it means
The deleteOutcomeProficiency mutation raises "Unable to find OutcomeProficiency" when OutcomeProficiency.active.find_by(id:) returns nil — no active record matches the parsed id, including soft-deleted proficiencies excluded by the active scope.
Solutions
- Verify the id via an OutcomeProficiency GraphQL query before deleting
- Confirm the record is active (workflow_state == active) in the DB
- Use the correct relay global id for the environment you are hitting
- Recreate the outcome proficiency if it was deleted unintentionally
Example fix
// before
record = OutcomeProficiency.active.find_by(id: record_id)
raise GraphQL::ExecutionError, "Unable to find OutcomeProficiency" if record.nil?
// after
record = OutcomeProficiency.active.find_by(id: record_id)
if record.nil?
raise GraphQL::ExecutionError, "Unable to find OutcomeProficiency (id: #{record_id})"
end Defensive patterns
Strategy: validation
Validate before calling
const prof = await query(outcomeProficiency, { id });
if (!prof) throw new NotFound(id); Type guard
function hasProficiency(p) {
return p?.data?.outcomeProficiency != null;
} Try / catch
try {
await client.mutate(DELETE_OUTCOME_PROFICIENCY, { id });
} catch (e) {
if (e.message === "Unable to find OutcomeProficiency") {
invalidateCache("outcomeProficiencies");
} else throw e;
} Prevention
- Validate ids against a fresh query before delete mutations
- Expect soft-deleted records to be unreachable via active scope
- Avoid caching proficiency ids across sessions
- Check environment/test-vs-prod data divergence
When it happens
Trigger: Calling deleteOutcomeProficiency with a nonexistent id, an already soft-deleted proficiency's id, or a malformed id that parses but matches nothing.
Common situations: Stale references after another admin deleted the proficiency scales, double-submitted mutations, or environments (test vs prod) with different data.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Unable to find OutcomeCalculationMethod
- Allocation rule not found
- Assignment not found
- assignment not found: #
- assignment not found
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/32ff148e85dfc0f6.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/delete_outcome_proficiency.rb:37
#
class Mutations::DeleteOutcomeProficiency < Mutations::BaseMutation
graphql_name "DeleteOutcomeProficiency"
# input arguments
argument :id, ID, required: true
# the return data if the delete is successful
field :outcome_proficiency_id, ID, null: false
def self.outcome_proficiency_id_log_entry(_entry, context)
context[:deleted_models][:outcome_proficiency].context
end
def resolve(input:)
record_id = GraphQLHelpers.parse_relay_or_legacy_id(input[:id], "OutcomeProficiency")
record = OutcomeProficiency.active.find_by(id: record_id)
raise GraphQL::ExecutionError, "Unable to find OutcomeProficiency" if record.nil?
raise GraphQL::ExecutionError, "insufficient permission" unless record.context.grants_right? current_user, :manage_proficiency_scales
context[:deleted_models][:outcome_proficiency] = record
record.destroy
{ outcome_proficiency_id: record.id }
end
end
View on GitHub (pinned to 1c9f0bb801)