From 6e92d2605d4461c2abbee5c0811344de028b67e8 Mon Sep 17 00:00:00 2001 From: Aadarsh Padiyath Date: Sat, 29 Aug 2026 16:01:51 -0500 Subject: [PATCH] Fix CodeTailor question lookup failing in cloned courses parsons_scaffolding resolved the activecode's question row with fetch_question(problem_id, basecourse=course.base_course). A cloned course keeps the original book's base_course on its question rows, and selectquestion can pull an exercise from another book, so that base-course-scoped lookup returns nothing and the endpoint 400s with "question '' not found" -- the student's "get help" button is dead. Fall back to a global name match (fetch_question(problem_id) with no basecourse) when the scoped lookup misses, the same resolution get_question_source and /htmlsrc already use. The scoped lookup still runs first so the single-book case is unchanged, and a warning is logged when the fallback fires so a genuine duplicate div_id across books stays diagnosable. The validated test case still comes from the resolved DB row -- no client-supplied code path. Co-Authored-By: Claude Sonnet 5 --- bases/rsptx/book_server_api/routers/coach.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/bases/rsptx/book_server_api/routers/coach.py b/bases/rsptx/book_server_api/routers/coach.py index e056790e5..eab00789a 100644 --- a/bases/rsptx/book_server_api/routers/coach.py +++ b/bases/rsptx/book_server_api/routers/coach.py @@ -396,6 +396,18 @@ async def parsons_scaffolding( try: basecourse = getattr(course, "base_course", None) question = await fetch_question(problem_id, basecourse=basecourse) + if not question: + # A cloned course keeps the original book's base_course on its + # question rows, and selectquestion can pull an exercise from + # another book, so the base-course-scoped lookup misses even + # though the question exists. Fall back to a global name match -- + # the same resolution get_question_source and /htmlsrc use. + question = await fetch_question(problem_id) + if question: + rslogger.warning( + f"CodeTailor: '{problem_id}' not in base course '{basecourse}' " + f"(likely a cloned course); resolved via global name match" + ) if not question: rslogger.error( f"CodeTailor: no question found for problem_id '{problem_id}'"