The following will cause Tcl to go into an infinite loop. Note the missing quote in the "error" command within the "while" block: ################################################################## proc test_expr {} { return 1 } proc test1 {} { set code [catch { while {[test_expr]} { error "missing ending quote } } msg] if {$code} {puts "$msg\n$::errorInfo"} } test1 #################################################################### Here's the byte code that shows what the problem is. It's the "jump1 0" at (5) that's causing the infinite loop. Compiling body of proc "test1" ByteCode 0x8236350, refCt 1, epoch 0, interp 0x8189308 (epoch 0) Source "\n\n set code [catch {\n\n while {[test_expr]} {\n" Cmds 4, src 163, inst 41, litObjs 7, aux 0, stkDepth 5, code/src 1.55 Code 252 = header 100+inst 41+litObj 28+exc 56+aux 0+cmdMap 16 Proc 0x8200cb0, refCt 1, args 0, compiled locals 2 slot 0, scalar, "code" slot 1, scalar, "msg" Exception ranges 2, depth 2: 0: level 1, catch, pc 5-3, catch -1 1: level 2, loop, pc -1--3, continue -1, break -1 Commands 4: 1: pc 0-17, src 6-116 2: pc 0-14, src 16-115 3: pc 18-39, src 123-160 4: pc 23-35, src 135-159 Command 1: "set code [catch {\n\n while {[test_expr]} {\n\n " Command 2: "catch {\n\n while {[test_expr]} {\n\n err" (0) beginCatch4 0 ===>(5) jump1 0 # pc 5 (7) push1 0 # "catch" (9) push1 1 # "\n\n while {[test_expr]} {\n\n " (11) push1 2 # "msg" (13) invokeStk1 3 (15) storeScalar1 0 # var "code" (17) pop Command 3: "if {$code} {puts \"$msg\n$::errorInfo\"}" (18) loadScalar1 0 # var "code" (20) tryCvtToNumeric (21) jumpFalse1 17 # pc 38 Command 4: "puts \"$msg\n$::errorInfo\"" (23) push1 3 # "puts" (25) loadScalar1 1 # var "msg" (27) push1 4 # "\n" (29) push1 5 # "::errorInfo" (31) loadScalarStk (32) concat1 3 (34) invokeStk1 2 (36) jump1 4 # pc 40 (38) push1 6 # "" (40) done If I understand what's going on correctly, the "jump1 0" was generated for the expression of the while loop as a "placeholder" until the body is compiled. As the body is compiled, the problem with the missing quote is encountered and the compiler code starts unwinding with an error status. The unwinding reaches "TclCompileScript()" at this point: if (code == TCL_OK) { goto finishCommand; } else if (code == TCL_OUT_LINE_COMPILE) { /* =====> * Restore numCommands to its correct value, removing * any commands compiled before TCL_OUT_LINE_COMPILE * [Bug 705406] */ envPtr->numCommands = savedNumCmds; } else { /* an error */ The error code was switched to TCL_OUT_LINE_COMPILE, so "numCommands" does get reset in "envPtr", but the compiled byte code (particularly the "jump1 0") doesn't get removed. This is what causes the infinite loop.