{"record":{"id":"42a9cf34c737c07c","repo":"instructure/canvas-lms","slug":"user-must-be-associated-to-rubric-before-llm-generation","errorCode":null,"errorMessage":"User must be associated to rubric before LLM generation","messagePattern":"User must be associated to rubric before LLM generation","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/services/rubric_llm_service.rb","lineNumber":193,"sourceCode":"\n  def resolve_generate_options(generate_options)\n    DEFAULT_GENERATE_OPTIONS.merge(generate_options.symbolize_keys)\n  end\n\n  def resolve_regenerate_options(generate_options, regenerate_options)\n    resolved = resolve_generate_options(generate_options)\n    resolved.merge(\n      additional_user_prompt: regenerate_options.symbolize_keys[:additional_user_prompt].presence ||\n                              resolved[:additional_prompt_info].presence ||\n                              \"No specific expectations, just improve it.\"\n    )\n  end\n\n  def validate_rubric_and_association_object(association_object)\n    unless association_object.is_a?(AbstractAssignment)\n      raise \"LLM generation is only available for rubrics associated with an Assignment\"\n    end\n    raise \"User must be associated to rubric before LLM generation\" unless @rubric.user\n  end\n\n  def call_llm_with_prefill(llm_config, prompt, root_account_uuid)\n    response = nil\n    time = Benchmark.measure do\n      response = CedarClient.conversation(\n        messages:\n         [{ role: \"User\", text: prompt },\n          { role: \"Assistant\", text: \"{\" }],\n        model: llm_config.model_id,\n        feature_slug: GENERATE_FEATURE_SLUG,\n        root_account_uuid:,\n        current_user: @rubric.user\n      ).response\n    end\n    [response, time]\n  end\n","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/rubric_llm_service.rb#L175-L211","documentation":"validate_rubric_and_association_object asserts @rubric.user is present before allowing LLM generation: the rubric must be owned by (associated to) a user. Rubrics owned by an account or otherwise lacking a user owner cannot use LLM criteria generation.","triggerScenarios":"Calling generate_criteria_via_llm or regenerate_criteria_via_llm on a rubric whose user_id is nil — e.g. an account-level rubric, a rubric created without user_context, or a rubric where ownership was never set.","commonSituations":"Admin/account rubrics opened in an editor that exposes the LLM button; rubrics imported/migrated without an owner; specs or scripts constructing Rubric.new without user assignment.","solutions":["Ensure the rubric is created in a user context so user_id is set before enabling LLM generation.","Hide/disable the LLM generate UI for account-owned rubrics.","Pre-check rubric.user in the controller and return a clear error instead of letting the service raise a bare string.","If an existing rubric lacks an owner, re-create it under the current user rather than mutating ownership directly."],"exampleFix":"// before\nRubricLlmService.new(rubric).generate_criteria_via_llm(...)\n// after\nif rubric.user.nil?\n  return render json: { error: 'rubric must be owned by a user for AI generation' }, status: :unprocessable_entity\nend\nRubricLlmService.new(rubric).generate_criteria_via_llm(...)","handlingStrategy":"validation","validationCode":"return head :unprocessable_entity if rubric.user.nil?","typeGuard":"def user_owned_rubric?(rubric)\n  rubric.respond_to?(:user) && rubric.user.present?\nend","tryCatchPattern":"begin\n  service.generate_criteria_via_llm(...)\nrescue RuntimeError => e\n  raise unless e.message == 'User must be associated to rubric before LLM generation'\n  render json: { error: 'rubric has no owning user' }, status: :unprocessable_entity\nend","preventionTips":["Create rubrics in user context so user_id is always populated when AI features are used.","Hide AI generation UI for account-owned rubrics.","Assert rubric.user in specs covering the LLM flow."],"tags":["rubric","llm","ownership","authentication-required"],"backgroundTag":"authentication-required","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"}