Documenting Tcl's warning/error messages

Purpose: provide a launching point for explanations and suggestions for resolving warnings and errors generated by the base Tcl interpreter.

Similar pages for extensions can be started if this appears useful.

The following is an attempt to catalog the various warning messages that a user might find appearing when running Tcl applications. The purpose of this list is not to simply have a list. It is to provide a point where people can add more explanation as to what a particular warning or error means, along with suggestions for solving the situation. In some cases, the solution may be a change in the user's environment. In other cases, the message may indicate an error in the Tcl application. In a few cases, the message may indicate a problem in Tcl itself.

        number of elements in list does not match count
        cannot use "*" in format string with "x"
        bad field specifier "{buffer}"
        not enough arguments for all format specifiers
        missing count for "@" field specifier
        expected {error1} but got "{error2}" instead

        wrong # args: should be "{command} option [args..]"
        wrong # args: should be "{command} {arg1} file"
        wrong # args: should be "{command} active file"
        wrong # args: should be "{command} display file"
        error accessing {file}
        wrong # args: should be "{command} onexit file"
        wrong # args: should be "{command} tag string"
        bad option "{option}": should be active, break_on_malloc, info, init, onexit tag, trace, trace_on_at_malloc, or validate
        wrong # args: should be "{command} {arg} count"
        wrong # args: should be "{command} {arg} on|off"
        wrong # args: should be "{command} filename"

        couldn't change working directory to "{dirname}": {posixerror}
        could not create new link "{path}": that path already exists
        could not create new link "{path}" using target "{path2}" doesn't exist
        could not create new link "{path}" pointing to "{path2}": {posixerror}
        could not read link "{path}": {posixerror}
        could not readlink "{path}": {posixerror}
        could not read "{path}": {posixerror}

        wrong # args: no script following "{clause}" argument
        wrong # args: no script following "else" argument
        wrong # args: extra words after "else" clause in "if" command
        "{command}" isn't a procedure
        "{command}" isn't a procedure
        "{command}" isn't a procedure
        couldn't store default value in variable "{varname}"
        procedure "{command}" doesn't have an argument "{argname}"
        bad level "{level}"
        list doesn't contain element {element}
        missing starting index
        "-command" option must be followed by comparison command
        "-index" option must be followed by list index
        element {element} missing from sublist "{list}" must be a list
        -compare command returned non-numeric result

        regexp match variables not allowed when using -inline
        couldn't set variable "{variable}"
        couldn't set variable "{variable}"
        extra switch pattern with no body
        extra switch pattern with no body, this may be due to a comment incorrectly placed outside of a switch body - see the "switch" documentation, or an "; # end switch" comment without the semi-colon.
        no body specified for pattern "{pattern}"
        bad operations "{flag}": should be one or more of rwua

        invalid encoding file "{file}"
        unknown encoding "{encodingname}"

        bad magic number in intermediate file "{filename}"
        couldn't open "{fileName}" : {posixerror}
        File "{fileName}" is not a Tcl load module.
        Library directory in "{fileName}" ends prematurely.
        bad magic number in intermediate file "{filename}"
        error on intermediate file "{filename}": {posixerror}

        couldn't load file "{filename}": {dlerror}

        initialization failed for dynamic loader: {dlderror}
        couldn't load file "{filename}}: {dlderror}
        initialization failed for dynamic loader: {dlderror}
        couldn't load file "{filename}": {dlderror}

        couldn't load file "{fileName}": {memoryerr}

        couldn't load file "{fileName}": {memoryerr}

        couldn't load file "{fileName}": {memoryerr}

        -handshake RTSCTS not supported for this platform
        -handshake DTRDSR not supported for this platform
        -ttycontrol DTR not supported for this platform
        -ttycontrol RTS not supported for this platform
        -ttycontrol BREAK not supported for this platform
        bad value for -handshake: must be one of xonxoff, rtscts, dtrdsr or none
        bad value for -xchar: should be a list of two elements
        bad value for -ttycontrol: should be a list of signal,value pairs
        bad signal for -ttycontrol: must be DTR, RTS or BREAK
        bad value for -mode: should be baud,parity,data,stop
        bad value for -mode: parity: should be n, o, e, m, or s
        bad value for -mode: parity: should be n, o, or 3
        bad value for -mode: data: should be 5, 6, 7, or 8
        bad value for -mode: stop: should be 1 or 2
        couldn't open "{filename}": {posixerror}
        can't get peername: {posixerror}
        can't get sockname: {posixerror}
        couldn't open socket: {posixerror}
        couldn't open socket: {posixerror}
        "{channel}" wasn't opened for writing
        "{channel}" wasn't opened for reading
        cannot get a FILE * for "{channel}"
        "{channel}" cannot be used to get a FILE *

        could not read "{filename}": {posixerror}
        could not read "{filename}": {posixerror}
        could not read "{filename}": {posixerror}
        could not set group for file "{filename}": group "{groupname}" does not exist
        could not set group for file "{filename}": {posixerror}
        could not set owner for file "{filename}": user "{username}" does not exist
        could not set owner for file "{filename}": {posixerror}
        could not read "{filename}": {posixerror}

        couldn't read directory "{dirname}": {posixerror}
        error getting working directory name: {posixerror}

        couldn't create pipe: {posixerror}
        couldn't fork child process: {posixerror}

        wrong # arguments: should be "{progname} option ... "
        bad index {pipenum}
        wrong # arguments: should be "{progname} clear index"
        wrong # arguments: should be "{progname} counts index"
        wrong # arguments: should be "{progname} create index readMode writeMode"
        couldn't open pipe: {posixerror}
        bad read mode "{readmode}"
        bad read mode "{readmode}"
        wrong # arguments: should be "{progname} empty index"
        wrong # arguments: should be "{progname} fill index" ??
        wrong # arguments: should be "{progname} fillpartial index" ??
        wrong # arguments: should be "{progname} wait index readable/writable timeout"
        pipe {pipename} doesn't exist
        bad option "{optionname}": must be close, clear, counts, create, empty, fill, fillpartial, oneevent, wait, or windowevent

        wrong # arguments: should be "{progname} file readable|writable|both timeout"
        bad argument "{argument}": must be readable, writable, or both
        wrong # arguments: should be "{command} argv0"
        wrong # args: should be "{command} channelName forWriting"
        Tcl_GetOpenFile succeeded but FILE * NULL!
        wrong # args: should be "{command} defaultDir"
        wrong # args: should be "{command} 
        sigaction: {posixerror"
        alarm: {posixerror"
        warning: sigaction SA_RESTART not support on this platformo

        wrong # arguments: should be "{command} option ... "
        bad option "{option}": must be done or wait

DKF: WARNING! The TCT and Core Maintainers make no general commitment to preserve any particular error messages. A higher level of commitment is made to preserving the errorCode contents (but only where they are not NONE) and code should match against that if possible. Use this page just to help when manually tracking down problems from unexpected error messages.

Also note that most of Tcl's built in commands generate their wrong # args: ... messages by calling a helper function, Tcl_WrongNumArgs, which handles the whole bunch of subtleties involved.

Schnexel: couldn't set loop variable ???

glennj: This happens if you use an array variable as a loop variable:

 array set varname {}
 foreach varname {1 2 3} break

Current Tcl error message is clear: can't set "varname": variable is array

Older Tcl message is more obscure: couldn't set loop variable: "varname"

Fabricio Rocha - 04-Feb-2010 - After more than 3 years, had there been any advances in Tcl's error handling? I am studying ways to implement error/exception handling in Tcl/Tk apps and, according to what I've read, relying on the error strings given by ::errorInfo is prone to problems, as DKF said; but ::errorCode contents are too limited for a clear detection of what happened, and even some core commands don't use appropriate error codes. By the way, some questions arise. Is there any way to translate the default error messages? I can only think that the solution is to override them all with translatable strings.

Lars H: Is the problem you perceive that errorCode cannot encode enough information, or just that most commands throwing errors don't bother supplying any information for it? I believe the latter case is generally (among the powers that be) considered as old bad habits, which the new try command should act as an incentive for breaking.

DKF: I've been working on improving things, but it's a gigantic and complex job. I welcome review by more sets of eyes. (Longer term, consider the error code space starting with the word TK to also be reserved, for obvious reasons...)

Fabricio Rocha - 05-Feb-2010 - Actually, from what I've read so far, ::errorCode, catch and return provide a very good infrastructure for error handling, and CAN provide enough information about errors, but they seem to be "underused" and, if they are not, there's a hole in the documentation. I can't assure by myself that even some core commands make bad or little use of this infrastructure (this is what I read in a comp.lang.tcl post mentioned in one page of this wiki), but as said here, "the standard ARITH, CHILD*, NONE, and POSIX only cover a fraction of all possible error conditions". If the error handling mechanisms are little used by the core itself, it's no wonder that third-party code uses it even less -- actually, tutorials and sample snippets very rarely tell to newbies like me that such infrastructure exists and should be used more often. So far, I have been using return just for returning values, as we usually do in C, and this have often left me scratching my head thinking how could I tell a caller proc that the returned value is actually an error code, while this feature is simply and beautifully built-in.

Maybe what I imagine for error handling could fit well in a tcllib package -- for example, a set of internationalized (or internationalizable) error messages, the possibility to have these messages shown in a Tk dialog rather than the console, facilities for treating specific errors properly while avoiding the interpreter or the whole script to collapse, and so on. I still haven't found out, for example, if there is a way to intercept and treat syntax and parsing errors in Tcl itself (by the way, where did the above list come from? From Tcl C sources?)

DKF: I'm working in 8.6 to expand the set of error messages. There are two particular categories of interest:

  • TCL WRONGARGS – used to indicate that the wrong number of arguments was passed (see human-readable message for details).
  • TCL LOOKUP type value – used to indicate that a search for a type with name value failed.

There are others that need documenting too. The actual error messages (as opposed to the errorCodes) are not documented precisely because they may change and are intended for human consumption.

Fabricio Rocha - These are indeed quite interesting categories. In fact, I think that the human-readable error messages are in a certain way self-documented. I presume that this have been discussed for years, but would it be possible that these human messages could be kept and generated in a "core package" in Tcl itself, updated (if needed) in each release, to which one could set a msgcat file with translated strings?

DKF: We're not going to run error messages through msgcat ourselves (for one thing, what about errors generated inside msgcat?) and we happen to think that code should normally not display any internal error messages from Tcl to users anyway as they are usually indicative of program bugs and not things that users can do anything about, but there's no reason at all for applications to avoid such a strategy as you suggest.

RZ Sometimes error messages are usefull p.e. "integer value too large to represent". But how should a developer detect these? Also the msgcat package work only on the script level. What about adding access to these functionality from the C-side. See Internationalization and the Tcl C APIs