FE Systems

---

The Wonderfulness of the
STACK TRACE facility of the
Tcl-Tk 'wish' interpreter

(OR: How the 'stack trace' system makes
testing and debugging of Tcl-Tk scripts
a relatively speedy, painless task.)

(FE = Freedom Environment)




FE Home Page > FE Downloads Page > FE 'tkGooies' Description Page >
Various 'tkGooies' CODE pages > This Page

Note: A few more examples of 'interesting' stack-traces
may be added occasionally.

< Go to Error Table of Contents, below. >
(SKIP THE INTRODUCTION)

Introduction to the Tcl-Tk 'stack trace' system :
(of the 'wish' interpreter)

One of the beauties of the Tcl-Tk script programming language is that Ousterhout (or others who helped him develop the 'tclsh' and 'wish' interpreters for the Tcl and Tk commands) seem to have invested a lot of thought and energy into developing the Tcl and Tk coding-error notification system --- the 'stack trace' system.

The error-notifications are so thorough that they almost make the testing-and-debugging process for Tcl-Tk scripts a pleasure rather than a chore.

Back in the 1960's, I was able to use the early FORTRAN compilers that were available from IBM. The error-notifications from my early FORTRAN coding attempts were often more cryptic than helpful.

So when I starting coding Tcl-Tk scripts in the 1990's, I was not just pleasantly surprised --- I was shocked at how thorough and helpful the messages were from my Tcl-Tk scripts as I tested and debugged the initial code for any of my 'apps'.

The error messages from FORTRAN compilers got better over the years (1960-1990, say), but I do not think that the FORTRAN messsages have ever approached the helpfulness of the Tcl-Tk error messages.

---

This is not to say that every coding error can be explicitly pointed out by the 'stack trace' system. But, with few exceptions, this is the case.

The following list of examples of output from the 'stack trace' system come from some of my testing-and-debugging 'sessions' on some of the Tk scripts of my 'tkGooies' FE subsystem.

Probably well over 50 percent of the errors that one makes in coding a long Tcl-Tk script are in spelling the names of widgets or variables one way in one portion of the script --- and then spelling the name slightly differently in another portion of the script.

The 'stack trace' system of the 'wish' (window shell) interpreter is particularly good at helping you catch those 'typos' in short order.

---

One of the more difficult error situations to pin-point is the case of a missing closing (right) brace.

In the list of traceback examples below, I provide some advice on how to locate those difficult-to-pinpoint error conditions.


Use of this page

You can use the links in the 'Table of Contents' section below to go to the discussion of a particular error message. OR ...

You can simply scroll down this page to get an idea of the typical kinds of 'stack trace' error messages (and error causes) that you encounter when testing-and-debugging Tk scripts. OR ...

If you are doing testing-and-debugging of a Tcl-Tk script, and you are getting an error message, you can use the Text-Search feature of your web browser to enter the text of an error message that you are getting --- to see if that message is described on this page --- and what a typical solution is, to resolve the error condition.

TABLE OF LINKS     (to error-message sections below)

        (in alphanumeric order by text near the start of the error message)


The 'missing close-brace' and 'wrong # args' messages can be errors for which it is most difficult to pin-point the cause. Hopefully the examples here can provide some guidance in how to proceed.

These examples of traceback messages came from testing-and-debugging some FE 'tkGooies' scripts.

The following list of Tcl-Tk 'traceback' error messages gives an idea of the messages I typically encounter when testing-debugging Tcl-Tk scripts.

END of Table of Contents/Links.

ERROR: 'bad window path name'

TYPICAL CAUSE #1: An undefined or mis-spelled widget name (in a 'pack' statement).

This is a very common type of error message when first testing some new code with the 'wish' interpreter.

This type of problem is very quickly resolved.

    Error in startup script: bad window path name ".fRfile1"
        while executing
    "pack .fRbuttons \
         .fRfile1 \
         .fRfile2 \
         .fRfactor \
         .fRgrid \
         .fRanifile \
         .fRguide \
         .fRstatus \
       -side top \
      ..."
        (file "./wheeeMorph.tk" line 1298)
    

This 'pack' statement was referring to a 'frame' widget that I had not defined.

I simply needed to add (or fix) a 'frame' definition statement for the frame name '.fRfile1'.

Note that the last line of the traceback told me that the error was in the main script --- not in a 'proc'. (See examples below in which the traceback indicates the error was found in a procedure.)

The first line of the error message --- 'Error in startup script:' --- also indicates that the error was in the main script.

The traceback pinpointed the error at line 1298. This number includes comment lines. Since I put a lot of comment lines at the top of my scripts, this error was actually near the top of the code lines (the non-comment lines) of the Tk script.

I typically do not use the line numbers to locate the error section of the code. I usually use the text-search feature of my text-editor. For example, in this case, I simply scrolled to a point below the copious comments at the top of the script and searched for the string '.fRfile1' --- to get to the area of the code that needed some attention.


ERROR: 'bad window path name'

TYPICAL CAUSE #2: Wrong path-name for a widget (a non-frame widget).

    Error in startup script: bad window path name ".fRfactor.scaleFACTOR"
        while executing
    "pack .fRfactor.label1FACTOR \
         .fRfactor.scaleFACTOR \
         .fRfactor.label2FACTOR \
       -side left \
       -anchor w \
       -fill none \
       -expand 0"
        (file "./wheeeMorph.tk" line 1590)
    

In this case, I had copied, from another Tk script, some code for defining and packing some widgets --- in a frame in which a 'scale' widget and a couple of 'label' widgets had been defined.

In using this 'pack' statement, I had forgotten to change the name of the frame in some preceding statements that defined the 'scale' and 'label' widgets --- to the '.fRfactor' frame name.

To correct this problem, I simply used the '.fRfactor' frame name in the several widget definition statements that preceded this 'pack' statement.

Note that the first and last lines of the traceback indicated that the error was in the main part of the script --- not in a 'proc'.


ERROR: 'bad window path name'

TYPICAL CAUSE #3: Wrong frame-name (in a widget definition statement).

    Error in startup script: bad window path name ".fRbottom.fRcanvas1"
        while executing
    "canvas .fRbottom.fRcanvas1.can \
       -width $initCanWidthPx \
       -height $initCanHeightPx \
       -relief flat \
       -highlightthickness 0 \
       -borderwidt..."
        (file "./wheeeMorph.tk" line 1934)
    

In this case, the path name '.fRbottom.fRcanvas1' was what I wanted to use. But I had not defined the 2nd-level frame name '.fRbottom.fRcanvas1' in a 'frame' statement above this 'canvas' definition statement.

To resolve this error, I simply needed to add an appropriate 'frame' statement.

Note that the first and last lines of the traceback indicated that the error was in the main part of the script --- not in a 'proc'.

ERROR: 'can't read ... no such variable'

TYPICAL CAUSE #1: An undefined variable.

    Error in startup script: can't read "scaleBKGD": no such variable
        while executing
    "scale .fRbuttons.scaleFACTOR \
       -orient horizontal \
       -from 0.00 -to 1.00 \
       -resolution 0.01 \
       -digits 3 \
       -length $initScaleLengthPx \
     ..."
        (file "./wheeeMorph.tk" line 1563)
    

The traceback did not display all the lines of the 'scale' definition statement. This statment included the line

      -bg $scaleBKGD \

to specify a background color for the trough of the 'scale' widget.

In this case, I had a 'set' statement that defined the variable 'scaleBKGD' --- but the statement was commented out. I simply had to uncomment the 'set' statement for this variable.

Note that the first and last lines of the traceback indicated that the error was in the main part of the script --- not in a 'proc'.


ERROR: 'can't read ... no such variable'

TYPICAL CAUSE #2: A variable name 'scope' declaration problem.

This is a fairly typical error condition --- and one that is easy to resolve 'in a flash'.

    can't read "DIRtemp": no such variable
    can't read "DIRtemp": no such variable
        while executing
    "set TEMPfilename1 "$DIRtemp/${fileMIDNAME}_img1.gif""
        (procedure "make_aniGIF" line 28)
    

In this script, I had failed to declare a variable 'DIRtemp' as a global variable in the proc 'make_aniGIF'. The solution was to simply add the name 'DIRtemp' to a 'global' statement at the top of the proc.

Note that at the bottom of this traceback, the name of the procedure and the line number in that procedure are pointed out.

Even if the line number does not help you find the problem-line, in a text-editor, you can simply position yourself at the top of the 'make_aniGIF' proc and then do a search for the string 'DIRtemp' --- to find statements that involve the specified variable name.


ERROR: 'can't read ... no such variable'

TYPICAL CAUSE #3: A variable name 'scope' declaration problem.

    can't read "aRi4point1ID(69)": no such variable
    can't read "aRi4point1ID(69)": no such variable
        while executing
    "set i $aRi4point1ID($moveID1)"
        (procedure "move_point1" line 39)
        invoked from within
    "move_point1 193 281"
        (command bound to event)
    

Once again I needed to add a variable name to a 'global' statement --- in the proc 'move_point1'.

In this case, the variable was an array variable. I simply needed to add the name 'aRi4point1ID' to a 'global' statement. I did not have to use the string '(69)' --- an index into the array.

Note that the traceback indicates that the 'move_point1' proc is being called from a 'bind' statement. This is indicated by the line '(command bound to event)'.


ERROR: 'can't read ... no such variable'

TYPICAL CAUSE #4: A executable character in double-quoted text.

    $ ./tkGnuplotXY_file2or3cols.tk
    Error in startup script: can't read "IMGDISPLAYpgm": no such variable
        while executing
    "set HELPtext "\
    \ \ ** HELP for this tkGUI FrontEnd for 'gnuplot' -
     to do X-Y plots of 2-or-3 data columns from a user-selected data file **
    
    This Tk..."
        (file "./tkGnuplotXY_file2or3cols.tk" line 2688)
    

In this case, I had put a dollar sign, with a variable name, within the lengthy text in this 'set' statement for a 'HELPtext' variable.

I needed to change the string

      $IMGDISPLAYpgm.

to

      \$IMGDISPLAYpgm.

within the double-quotes of the 'set' statement for the 'HELPtext' var.

The back-slash (escape character) told the 'wish' interpreter not to try to interpret the dollar-sign character like it normally does. Just leave it as a dollar-sign character.


ERROR: 'can't read ... no such variable'

TYPICAL CAUSE #5: An incomplete 'set' statement.

    $ ./tkGnuplotXY_file2or3cols.tk
    Error in startup script: can't read "COLORAXISr": no such variable
        while executing
    "set COLORAXISr"
        (file "./tkGnuplotXY_file2or3cols.tk" line 2819)
    

I needed to supply a value to the 'set' statement, such as

      set COLORAXISr 0

When you use 'set' on a variable name (with nothing following the variable name), the interpreter thinks that you want to know the value of the variable. When using 'set' as a query, the variable must have been defined elsewhere. That was not true in this code --- hence the 'can't read ... no such variable' error.

ERROR: 'invalid command name'

TYPICAL CAUSE: A mis-spelled widget name.

    (spelled differently from the name used in
    the statement in which the widget was defined)

This is a very common error that is seen in debugging Tk GUI scripts.

It is typically a problem of spelling a name one way in one part of the script, and then spelling the name slightly differently in another part of the script.

    invalid command name ".fRfile.entFILENAME1"
    invalid command name ".fRfile.entFILENAME1"
        while executing
    ".fRfile.entFILENAME1 xview end"
        (procedure "get_img1_filename" line 29)
    

I needed to change a frame widget name '.fRfile' to '.fRfile1'.

This frame '.fRfile1' was defined in a 'frame' statement near the top of this script. But I referred to it as '.fRfile' in this 'xview end' statement --- whose purpose is to show the end of the filename to show in an entry widget.

Note that the last line of the traceback told me that the error was in the procedure 'get_img1_filename' --- at line 29.

Note that the error message said 'command name' rather than 'widget name'. This is because after a widget (like a 'frame' or a 'button' or a 'label' or a 'radiobutton' or a 'listbox' or ...) is defined, it becomes a command. And text that appears after that command name (widget name) becomes arguments to the command. In this case, the text 'xview end' were arguments (inputs) to the widget/command.

ERROR: 'expected integer but got'

TYPICAL CAUSE: A missing dollar-sign (to indicate a variable name).

    $ ./tkGnuplotXY_file2or3cols.tk
    Error in startup script: expected integer but got "COLORLINEr"
        while executing
    "format "#%02X%02X%02X" COLORLINEr COLORLINEg COLORLINEb "
        invoked from within
    "set COLORLINEhex [format "#%02X%02X%02X" COLORLINEr COLORLINEg COLORLINEb ]"
        (file "./tkGnuplotXY_file2or3cols.tk" line 2822)
    

In a 'format' statement, I needed to add a dollar sign ($) in front of 3 COLOR variable names:

   set COLORLINEhex [format "#%02X%02X%02X" $COLORLINEr $COLORLINEg $COLORLINEb ]

ERROR: 'extra characters after close-quote'

TYPICAL CAUSE: A missing right-parenthesis (in an array variable name).

    Error in startup script: extra characters after close-quote
        while executing
    "radiobutton  .fRwindowsLayout.radbuttLAYOUT3x2 \
       -text "$aRtext(radbuttLAYOUT3x2" \
       -font fontTEMP_varwidth \
       -anchor w \
       -variable RADVAR..."
        (file "./find_and_AniGifViewers_FrontEnd.tk" line 997)
    

This 'radiobutton' statement is defining a widget/command named

    '.fRwindowsLayout.radbuttLAYOUT3x2'.

On the line that provided the '-text' for the radiobutton, I had failed to provide a right-parenthesis to close-off the index of the 'aRtext' array element. I needed a right-paren after the characters '3x2'.

Note that this error was in the main script --- not in a 'proc'. This was indicated by 'Error in startup script:' at the top of the traceback messages.

ERROR: 'invalid command name "..."'

TYPICAL CAUSE #1: A mis-spelled procedure name.

    invalid command name "put_img1_on_canvas"
    invalid command name "put_img1_on_canvas"
        while executing
    "put_img1_on_canvas"
        (procedure "load_2files_to_canvases" line 63)
    

In this case, I needed to change the call to procedure 'put_img1_on_canvas' to 'put_img1_on_canvas1' --- in other words, simply add the character '1' to the end of the call statement.

The proc existed. I just needed to use the right name.

Note that at the bottom of this traceback, the name of the procedure, that was calling the mis-spelled procedure name, was pointed out.

Note that this same error message had occurred in an example above --- where the 'invalid command name' was a widget name --- which is a command name, as was explained there. So sometimes the 'command name' is not a 'proc', but a widget name.


ERROR: 'invalid command name "..."'

TYPICAL CAUSE #2: An executable character in double-quoted text.

    $ ./tkGnuplotXY_file2or3cols.tk
    Error in startup script: invalid command name "x"
        while executing
    "x and y axis"
        invoked from within
    "set HELPtext "\
    \ \ ** HELP for this tkGUI FrontEnd for 'gnuplot' -
     to do X-Y plots of 2-or-3 data columns from a user-selected data file **
    
    This Tk..."
        (file "./tkGnuplotXY_file2or3cols.tk" line 2688)
    

I had put square brackets within the lengthy text in this 'set' statement for a 'HELPtext' variable.

In other words, I had put square brackets in double-quotes --- unprotected from the 'wish' interpreter. The line in the text was

   x-axis and y-axis titles, x and y axis limits, [x and y axis
   tic-mark intervals (someday?)], plot lines points or both,

I moved the bracketed info down below this sentence, and removed the square brackets.

An alternative would have been to 'escape' the brackets by putting a back-slash character immediately to the left of each of the brackets.


ERROR: 'invalid command name'

TYPICAL CAUSE #3: Used the wrong (undefined) name for a widget.

    $ ./tkGnuplotXY_file2or3cols.tk
    Error in startup script: invalid command name ".fRbuttons.buttCOLORline"
        while executing
    ".fRbuttons.buttCOLORline configure -bg $COLORLINEhex"
        (procedure "update_line_color_button" line 8)
        invoked from within
    "update_line_color_button"
        (file "./tkGnuplotXY_file2or3cols.tk" line 2823)
    

I needed to change ".fRbuttons.buttCOLORline" to the existing name ".fRbuttons.buttLINEcolor" --- in the proc 'update_line_color_button'.

In the procedure 'update_line_color_button', the 'configure -bg' arguments to a 'button' widget/command were being used to change the background color of a button widget.

This is a case where, when I was writing the code for the proc, I guessed at the name that I had used in the main part of the Tk script --- to define the 'button' widget. I guessed wrong.

ERROR: 'missing close-brace: possible unbalanced brace in comment'

TYPICAL CAUSE: A missing right-brace within a 'proc'.

    Error in startup script: missing close-brace: possible unbalanced brace in comment
        while executing
    "proc make_aniGIF {} {
    

This 'missing close-brace' error is probably the most difficult to track down.

In this 'make_aniGIF' proc, I found the missing brace, quite a few statements down in this proc.

Whenever I got this error, I used to carefully read every line of the indicated 'proc' to look for a missing 'close-brace'.

And, if I were really stumped, in a proc with many lines and many braces, I felt forced to remove lines of code until I removed a line that made the error go away --- or remove all the lines (say paste into a different text-editor window) and start placing the lines back one by one until the error showed up again.

I finally found a better way that usually works for me. I use the 'scite' text editor which has a nice character high-lighting feature.

If you put the text-cursor next to a 'left' character like a left-brace or left-parenthesis or left-bracket, the 'scite' text editor highlights that character and then highlights (in blue) the next matching 'right' character --- a right-brace or right-parenthesis or right-bracket.

If the wrong character is high-lighted, you have found your missing 'close' character.

Often the problem is simply that a right-parenthesis was typed instead of a right-brace, for example.

---

Note the 'possible unbalanced brace in comment' part of the error message. This refers to a peculiarity of the 'wish' Tcl-Tk interpreter --- and the Tcl-only 'tclsh' interpreter.

The Tcl-Tk interpreters scan comment statements --- as well as 'regular code statements' --- for braces. If you have a brace in a comment statement and it is not 'balanced' by a close-brace, a 'show-stopping' (interpreter stopping) error message will be triggered.

As a matter good Tcl-Tk coding practice, it would be good to avoid putting ANY braces in comment statements. If you need to do so, be sure to 'balance' them.

ERROR: 'missing close-bracket'

TYPICAL CAUSE: Missing right-bracket --- in an 'if' statement (or when using 'expr').

    missing close-bracket
    in expression "![info exists MINIMGwidt..."
    missing close-bracket
    in expression "![info exists MINIMGwidt..."
        (parsing expression "![info exists MINIMGwi...")
        invoked from within
    "if {![info exists MINIMGwidthPx} {return}"
        (procedure "popup_img3" line 14)
        invoked from within
    "popup_img3"
        invoked from within
    ".fRbuttons.buttSHOWIMG3 invoke"
    

I needed to add a right-bracket to properly enclose an 'info exists' statement.

Note that the traceback pointed out that the statement that was missing the bracket was in proc 'popup_img3' --- at line 14. And the traceback indicated that this proc was being called by ('invoked' by) the button widget '.fRbuttons.buttSHOWIMG3'.

This example indicates why these sets of error messages are called a 'traceback' or 'stack trace'. The error message indicates an error line --- then indicates a 'proc' that called the error line, if any --- then indicates what called that 'proc', if anything --- and so on.

ERROR: 'missing operator at'

TYPICAL CAUSE: A missing, leading double-quote.

    missing operator at _@_
    in expression "$RADVARoutimg_@_" == "gif""
    missing operator at _@_
    in expression "$RADVARoutimg_@_" == "gif""
        (parsing expression "$RADVARoutimg" == "gif"")
        invoked from within
    "if {$RADVARoutimg" == "gif"} {
          puts $SHout "set terminal gif size $Xpixels , $Ypixels"
          set IMGfile "$DIRout/${userID}_temp.gif"
          set ..."
        (procedure "replot" line 57)
    

In the procedure 'replot, in an 'if' statement, I was missing a leading a quote in:

   if {$RADVARoutimg" == "gif"} {

It should have been

   if {"$RADVARoutimg" == "gif"} {

ERROR: 'too many colors'

TYPICAL CAUSE: An image-type problem.

    too many colors
    too many colors
        while executing
    "IDimgTEMP write "$TEMPfilename" -format gif"
        (procedure "make_aniGIF" line 117)
    

In this case, I had built an in-memory image consisting of more than 256 different colors. When I tried to write out the image as a GIF file (which is limited to a max of 256 colors), the interpreter protested.

A solution was to use '-format ppm'. The PPM format supports many more than 256 colors --- at least 16 million.

    (Unfortunately, PPM is not a compressed image format. So ultimately, one would want to convert this file to a more compressed format such as PNG. Actually, in this case, a set of PPM files were used to make an animated GIF file, which uses a compression algorithm.)

ERROR: 'wrong # args'

TYPICAL CAUSE #1: A missing left-brace --- in an 'if' statement.

    $ ./tkGnuplotXY_file2or3cols.tk
    Error in startup script: wrong # args: should be "proc name args body"
        while executing
    "proc replot {} {
    
       global DIRout env DATAfilename
       global PlotTITLE XaxisTITLE Y1axisTITLE Y2axisTITLE
       global Xcolnum Y1colnum Y2colnum
       glob..."
        (file "./tkGnuplotXY_file2or3cols.tk" line 1651)
    

This is one of those types of errors in which it can be challenging to find the exact source of the error.

This was NOT a problem with the number of arguments passed to this proc.

Further down in this proc 'replot', in a statement not shown in this traceback, I had a left-parenthesis instead of a left-brace in an 'if' statement:

   if ("$Y2colnum" != ""} {

I changed it to:

   if {"$Y2colnum" != ""} {

This is one of those cases where it is helpful to use a text-editor that highlights a closing brace/paren/bracket when you put the text cursor next to a starting brace/paren/bracket --- or highlights a starting brace/paren/bracket when you put the text cursor next to closing brace/paren/bracket.

You can step through the proc putting the text-cursor next to each starting brace (or paren or bracket), and see what character is high-lighted somewhere beyond the location of the text-cursor.


ERROR: 'wrong # args'

TYPICAL CAUSE #2: A missing pair of braces --- in a 'proc' definition.

    $ ./tkGnuplotXY_file2or3cols.tk
    Error in startup script: wrong # args: should be "proc name args body"
        while executing
    "proc enable_disable_xaxis_widgets {
    
       global useXaxisParms_0or1
    
       if {$useXaxisParms_0or1 = 0} {
          .fRxaxis.labXmin configure -state disabled
    ..."
        (file "./tkGnuplotXY_file2or3cols.tk" line 2369)
    

This is one of those error situations in which it may be easy to overlook the cause of the error.

I was missing '{}' in the proc statement:

      proc enable_disable_xaxis_widgets {

I needed to change it to:

      proc enable_disable_xaxis_widgets {} {

Even though I did not need any 'arguments' for this proc, the Tcl 'proc' statement requires the pair of braces that are ordinarily used to list any arguments for the proc.

IN CONCLUSION:

I may add a few more examples of 'wish' interpreter 'stack trace' messages --- if I find any that are distinctly different from the ones above.

In any case, I hope that this web page conveys my experience that the 'error notification system' of the Tcl-Tk 'wish' interpreter provides the most helpful testing-and-debugging system that I have ever seen.

Bottom of the page that points out the
Wonderfulness of the STACK TRACE system of the 'wish' interpreter.

To return to a previously visited web page location, click on the
Back button of your web browser a sufficient number of times.
OR, use the History-list option of your web browser.
OR ...

< Go to Top of Page, above. >

Page was created 2016 Jul 27.
Page was changed 2016 Oct 26. (Added Table of Contents/Links and rearranged examples.)