How Do i Fix Python Turtle Game Crash Error When I Close the Window Manualy

I made a simple shooter game using the Python turtle module. It’s fun, easy to code, and beginner-friendly! But while I was playing around with it, I ran into a frustrating problem. Every time I closed the turtle graphics window manually (like just clicking the [X] on the window), my program crashed with a long, scary-looking error message. But weirdly enough if I let the game finish on its own and then closed it, everything worked fine.

The Game Code

Here’s the original game code I wrote. It creates a player-controlled turtle at the bottom of the screen that can shoot bullets upward to destroy falling enemy blocks.

import turtle
from random import randint

wn = turtle.Screen()
circle1 = turtle.Turtle(shape='circle')
bullet = turtle.Turtle(shape="circle")
bullet.ht()
bullet.speed(0)
circle1.speed(-1)
circle1.penup()
circle1.ht()
circle1.sety(-270)
circle1.st()

wn.setup(300, 600)

enemies = []
score = 0
prevscore = 1
speed = 10

for i in range(10):
p = turtle.Turtle(shape='square', visible=False)
p.speed(0)
p.penup()
p.color('blue')
x = randint(-240, 240)
y = randint(180, 360)
p.goto(x, y)
p.showturtle()
enemies.append(p)

def enemy_move():
global game_on, speed, score, prevscore

for p in enemies:
y = p.ycor()
p.sety(y - speed)

if p.ycor() < -300 or p.distance(bullet.pos()) < 30:
if p.distance(bullet.pos()) < 30:
score += 1
p.hideturtle()
y = randint(180, 360)
p.sety(y)
p.showturtle()

if circle1.isvisible() and p.distance(circle1.pos()) < 20:
p.hideturtle()
circle1.hideturtle()
game_on = False
wn.clear()
circle1.goto(0, 0)
circle1.write(f"Your final score is {score}", align="center", font=("Arial", 26, "normal"))

if game_on:
if score % 10 == 0 and score != prevscore:
speed += 0.5
prevscore = score

wn.ontimer(enemy_move, 50)

game_on = True
enemy_move()

def goright():
if circle1.xcor() < 130:
circle1.seth(0)
circle1.fd(10)

def goleft():
if circle1.xcor() > -130:
circle1.seth(180)
circle1.fd(10)

def shoot():
bullet.penup()
bullet.goto(circle1.pos())
bullet.seth(90)
bullet_move()
bullet.showturtle()

def bullet_move():
if bullet.ycor() <= 300:
bullet.sety(bullet.ycor() + 10)
wn.ontimer(bullet_move, 50)
else:
bullet.hideturtle()

wn.listen()
wn.onkeypress(goright, "Right")
wn.onkeypress(goleft, "Left")
wn.onkeypress(shoot, "Up")
wn.mainloop()

The Error I Got When I Closed the Window

Here’s what appeared in the console when I manually closed the window while the game was running:

_tkinter.TclError: invalid command name ".!canvas"

Explain Error

This error is coming from Tkinter, which is the GUI engine that turtle is built on top of.

The short version:
When you use ontimer() to run a function after a delay (like in my game loop), it keeps trying to run even after the turtle window is gone. But since the canvas is already destroyed when I close the window manually, Python crashes when it tries to update it.

So yeah, the ontimer() callback is still firing but there’s nothing left to draw on. That’s what the error means when it says:

It literally means: “I don’t know what ‘canvas’ you’re talking about.

"invalid command name '.!canvas'"

How I Fix It

To fix this, I wrapped the animation function (enemy_move) in a simple try-except block and checked if the window is still open before doing anything else.

Here’s the updated enemy_move() function with the fix:

def enemy_move():
global game_on, speed, score, prevscore
if not wn._rootwindow:
return # Stop if the window is closed

try:
for p in enemies:
y = p.ycor()
p.sety(y - speed)

if p.ycor() < -300 or p.distance(bullet.pos()) < 30:
if p.distance(bullet.pos()) < 30:
score += 1
p.hideturtle()
y = randint(180, 360)
p.sety(y)
p.showturtle()

if circle1.isvisible() and p.distance(circle1.pos()) < 20:
p.hideturtle()
circle1.hideturtle()
game_on = False
wn.clear()
circle1.goto(0, 0)
circle1.write(f"Your final score is {score}", align="center", font=("Arial", 26, "normal"))

if game_on:
if score % 10 == 0 and score != prevscore:
speed += 0.5
prevscore = score

wn.ontimer(enemy_move, 50)

except turtle.Terminator:
print("Game exited safely.")

I also updated the bullet_move() function similarly to prevent it from causing the same error.

Code Improvement I Want to Add

Now that the crash is fixed, I’m thinking of expanding the game with some extra functionality for practice:

  • Show a live score during gameplay
  • Add multiple bullets or a bullet cooldown
  • Introduce levels or faster enemies as the score increases
  • Track high scores using file I/O
  • Add a restart option after game over
  • Maybe even a health system (3 hits before losing)

Final Thought

This project started as a fun beginner game with Python Turtle, and it was going great until that unexpected crash ruined the experience.

But I’m actually glad it happened it taught me something important about how event loops and GUI windows work under the hood in Python. And it turns out, the fix was pretty simple: just make sure you don’t try to update the screen after it’s closed.

Related blog posts