Found by a cache-correctness review sweep.
src/canvaslms/cli/results.py:148 (results.nw) computes round_to_day(submission.submitted_at or submission.graded_at); round_to_day (results.py:210) does timestamp.split("T"). If a submission has a non-None grade but both submitted_at and graded_at are None (which occurs for some manually-entered or excused entries), the summary aborts with AttributeError: 'NoneType' object has no attribute 'split'.
Suggested fix: guard the both-None case in the caller (skip the date or emit an explicit empty date) in src/canvaslms/cli/results.nw, with a test.
Severity: low.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Lz1Ft1GN2YqQ6YGLGVYZdT
Found by a cache-correctness review sweep.
src/canvaslms/cli/results.py:148(results.nw) computesround_to_day(submission.submitted_at or submission.graded_at);round_to_day(results.py:210) doestimestamp.split("T"). If a submission has a non-None grade but bothsubmitted_atandgraded_atare None (which occurs for some manually-entered or excused entries), the summary aborts withAttributeError: 'NoneType' object has no attribute 'split'.Suggested fix: guard the both-None case in the caller (skip the date or emit an explicit empty date) in
src/canvaslms/cli/results.nw, with a test.Severity: low.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Lz1Ft1GN2YqQ6YGLGVYZdT