(CRITICAL) Upgrading from versions prior to version 28 of the Operating System will reset the datalogger’s CPU drive. This is due to a change in the format of the file system from FAT16 to FAT32. In order for the datalogger to operate correctly, as part of the upgrade, the CPU drive is formatted to FAT32. Any programs stored and running from the CPU drive will be lost. It is not recommended to update the datalogger’s Operating System over a remote connection where program control regulates the communication equipment (turning it on or off, etc.). In these cases, an on-site visit and a backup using DevConfig’s backup utility is necessary to update the datalogger’s Operating System. In all cases where the datalogger is being updated with an Operating System prior to 28, the use of DevConfig’s backup utility is recommended due to the fact that the CPU drive is formatted using the new FAT32 format. Watch the Video Tutorial: Sending an OS to a Local Datalogger.
(WARNING) There is a known issue with this operating system when using CDM devices. If the cable is pulled from the CDM device or from the datalogger while the CDM device is running, the datalogger may not be able to get the CDM device running again. The datalogger will require a restart via a power cycle or by resending the program to get the CDM device working again. Please contact Campbell Scientific to receive a beta operating system that resolves this issue. The issue will also be fixed in the next release of the datalogger operating system.
(CRITICAL) This operating system is not compatible with earlier beta CDM OSs. Make sure the CDMs are running operating system version 1.0.
Added a check for Alias names that already exist as variables.
Fixed VibratingWire() when it is used outside of Scan() / NextScan and has Reps greater than 1.
Modified TableFile() to return an error upon detecting an invalid drive (CPU:). Before it would try to establish drive parameters and this would send the datalogger into a continuous compile loop.
Reordered the keyboard display configuration so the Constant table and the Field Calibration, if present, are above the settings.
Fixed SDI12SensorSetup() when the source variable is of type LONG.
Fixed SDI12SensorSetup() to respond to 'V' command when the 'D!' command does not come right away, as is the case when driving the sensor via the terminal mode.
Modified SDI12Recorder() by adding an optional parameter and the ability to work with multiple sensors in a single instruction call.
Fixed SDI12SensorSetup() where in some cases it would send trailing zeroes after the decimal.
Added optional parameter to SDI12Recorder() to fill array with NAN when communications fail.
Modified the operating system so when the use is in the SDI12 terminal, if "SDI12 Failed" appears or happens, exit SDI12 terminal.
Modified the operating system so when editing the constant table via the keyboard display do not ask the user to "Save Changes?" if backing out of a change.
Modified the operating system so the table names of hidden tables are blanked out in DataTableInfo.
Fixed double precision Sprintf() with the Format %Lf and the number is larger than 14. Also allowed the precision digits to go to 15 instead of 14.
Modified the operating system so PakBus instructions (ie. SendData(), SendGetVariables(), SendVariables(), etc.) are forced to use a static route unless the ComPort parameter is set to 0. If the ComPort parameter specified is set to 0 and a dynamic route exists, the dynamic route will be used instead.
Fixed streaming data in FTPClient(), EmailSend(), HTTPPost(), etc. when an element within an array is specified that is part of a table and that variable is being streamed.
Fixed EmailSend() when streaming from a data table that does not exist. When this was done previously, it would watchdog the datalogger.
Fixed an issue when using large constant table, CPI table, and table information when the size of the data in the table exceeded the PakBus maximum packet size. The issue was seen when displaying the table in any Campbell Scientific software that displays the datalogger tables.
Fixed the operating system so when parsing parameters with trailing spaces caused an error in the case where an optional parameter was not present.
Fixed ArrayLength() so it reports the size correctly. There were certain conditions where it would report erroneously.
Fixed the keyboard display’s categorization of settings.
Fixed the spelling of comports in the keyboard display to display Comports instead.
Fixed the sort used with Median() and SortSpa() to put NAN always at the beginning of the array.
Changed Erase() instruction to allow a variable index in the EraseVar parameter.
Modified the start of the process of updating PakBus neighbor information to routers from 0 to 1 seconds to 0 to 15 seconds to help with congestion when an update is necessary.
Changed GOESData() to allow a constant declaration of the data table name. (This also fixes GetRecord() when the optional Format parameter was added to also work with a constant declared table name.)
Changed the minimum gap time on all but control ports for Modbus to 30 milliseconds instead of 20 milliseconds. The CR3000 could not handle a gap time of 20 milliseconds on SDC.
Added a new LineNum() instruction.
Fixed the streaming Public and Status tables.
Changed FTPClient() so the response code of 230 (logged in) is accepted after issuing the user name.
Modified Settings.SDCInfo so it is set to a null string if no SDC device is attached.
Modified the operating system to update the Response parameter if used to store the file name in HTTPGet() when Files Manager is active.
Fixed an issue with the datalogger reporting Card OK when there was an error with the card.
Added an optional Timeout parameter to TCP Client instructions (HTTPGet(), FTPClient(), HTTPPost(), EmailSend(), etc.).
Modified the operating system to allow 4 optional parameters (NumRecs/TimeIntoInterval, Interval, IntervalUnits, FileOption) for IP data table streaming to be blank, as in ,,,, to get to the new Timeout parameter in EmailSend(), FTPClient(), HTTPPost(), etc.
Added redirection to a different URL in HTTPGet() when the webpage returns with a 302 status code.
Added more categories to the keyboard display in the settings menu to correspond with the tabs in the settings editor of DevConfig.
Fixed the timeout so it will be more precise when trying to get a TCP/IP address that was retrieved from a domain name server (DNS).
Added a new command line options to the PC pre-compiler. -i works like -p but expands non-encrypted include files into the specified output file.
Added HTTP Header setting to DevConfig and the datalogger.
Fixed ^ power operator when an operand is of type DOUBLE.
Fixed uploading a .gz file. Modified the timeout and now return an error if takes too long and return an error if cannot allocate space for the task.
Modified GoesData() format 0 and 1 so it now will convert any data type to FP2.
Added optional parameters to DisplayMenu() and SubMenu() to specify the default line to show the cursor at.
Modified the messages for IP networks that are powered down to be less ambiguous.
Modified the operating system so TPC/IP over CSIO(1,2) when they are not active to filter out packets except when sent a shutdown packet.
Modified GetRecord() by adding an optional "format" parameter with the GOES format options. The parameter is variable. A fixed -1 format acts as if the parameter was not present.
Fixed an issue with FTPClient() when under some conditions of failure it would return 0 instead of a connection handle.
Modified the operating system so when reading string settings it accommodates, in all cases, fragmentation of the string.
Changed TCPClose() to wait for remote to ACK to close and abort instead of closing if the state is not established. This prevents holding on to memory too long (over one minute) and cause a problem with rapid TCPOpen() and TCPClose().
Fixed ModBus RTU on ComUSB and ComRS232.
Modified SerialClose() to allow shut down RS232 power unless always on or handshaking settings are active.
Fixed SendData() so when the optional parameter (Number of Records) is > 0 then it will send that many records back regardless if there are no new records stored since the last execution.
Added new power mode setting for the CR1000 and CR3000 that matches a similar setting on the CR6.
Changed the settings tabs that are displayed by DevConfig.
Fixed IPv6 having duplicate entries in the router list.
Fixed code in comport timeouts controlling comport off and also controlling ModBus RTU timeouts.
Modified CommsMemFree to not show the third line (IP PBUFS) if there are not any networks enabled. In this case this memory does not exist.
Added the ability to do ModBus RTU over USB with working timeouts.
Fixed FileGet() if the request for a swath is 0.
Fixed a slow slicing problem with the AM25T.
Fixed network enable setting to recompile when necessary.
Modified the DHCP server if there are no networks enabled. This was done so the logger would not try to allocate memory for a network that does not exist.
Fixed recursive calls to TCPOpen() when there is no network active and there is a PakBus TCP ClientSetting. Previously this would cause memory corruption.
Changed dhcps_init() so the DHCP server starts up again after it has been closed.
Modified the binary 'W' monitor so it is now again compatible with Log View.
Fixed ip_frag.c LWiP stack bug when fragmenting a TCP packet and the packet needs to be resent, i.e., it is not ACKED. This could have caused a memory corruption and watchdogs caused by the ip task looping inside ip_frag() forever.
Changed receiving PakBus Get and Send variables to accept little endian longs (CSILONG, data type type 20).
Fixed PPP to not leak memory (PBUF_POOL) in the event that the comport task for the PPP interface is not running or in the event that we run out of services.
Fixed wireless sensor instructions when the configuration parameter is an expression using the & operator.
Modified the datalogger web service so it does not eliminate the security= command but rather nulls the string after the last digit in the command so only the security is copied into the links rather than a possible XXS string.
Fixed TableFile Mode 64 output occurring at the same time as FileMark.
Modified the PPP start up after reset and dial connect to hold off for 2 seconds. The Sierra Modems expect some hold off after dial connect else they keep echoing.
Implemented range checking parsing the processing field when changing settings via keyboard display, CRBasic, or remotely.
Changed the Terminal W watch binary to now include ASCII characters.
Chanded SolarPosition() so the TimeOffset parameter can now be variable as well as a constant.
Changed NewFile() to allow FileName to be an expression.
Added StationNameSetting to the pre-defined constant list. Its value is the station name setting of type string.
Added optional parameter to the Resistance() instruction to return the measured current as the last measurement in the array.
Fixed initializing boolean variables so a non-zero value is set to -1 (TRUE).
Modified the operating system to now discard Ethernet packets whose MAC address is our own.
Fixed a memory leak of PBUF_POOL in the event an https client which tries to connect on port 443. In the CR1000, CR3000, and CR800.
Modified the operating system so when the station name is changed, restart DHCP on all the networks.
Fixed HTTP newest record date/time for Status and Public tables.
Added New PakBus windowing get and receive file and data collect commands.
Modified terminal W mode to only abort if the different connection is not PakBus or telcom or if the character coming in is CR or ESC.
Removed disabling PPP if the DEL key is pressed and held on the keyboard display that aborts a program running.
Changed PPP ECHO REQUEST response timeout for 1 try (2 tries total) to 105 seconds from 90 seconds, so the total timeout is 3.5 min instead of 3 min.
Changed the operating system so while polling TCP connections, if any connection is using a local IP address that is not the IP address of a network (PPP, Ethernet, Wi-Fi, etc.) then close the connection.
Fixed PC pre-compiler issue where Windows XP 32-bit users could not use the pre-compilers. All logger pre-compilers are now 32-bit operating system compatible.
Added CR300 to list of predefined constants, so programs can use it in LoggerType.
Fixed PC pre-compiler crash when using ConstTable with no name.
Allow Get/Send values to specify the "Settings" table along with "Status" to get or set settings.
Changed DataTable: If a user specifies only 1 record, provide only one record. This allows for multiple "public" type tables.
Fixed sprintf() with the '*' specifying dynamic width or precision.
Fixed NewFieldNames() when the entire generic array is named and an attempt is made to rename the fields again.
Changed the keyboard display pick list when working with a constant table.
Fixed EssVariables() when used in the same program as SNMPVariable().
Modified the operating system to allow ping via a PPP network to ping yourself instead of flagging an echoing error.
Fixed the code for GPs. It now sends the entire GPRMC string even if the GPS does not have a valid fix. Previously, the string was only sent if the 'A' was returned in the fix location.
Added a compile error if a Constant Table has the same name as another table, including the "settings" table.
Modified the PC pre-compiler to Allow up to 1000 warnings. This same process is limited to 3 in the datalogger. This was done because we enabled the unused variable check which would require many more listings than just three.
Fixed an error with ModBus TCP to RTU datagram.
Added line number information for the PC pre-compiler when reporting unused variables.
Enabled GPS() so it will work without a PPS signal. This is activated by using COMnum < 0 in the instruction.
Added a special PakBus DataGram destination ID of 506 which translates TCP ModBus into RTU ModBus.
Fixed promoting to float operands preceding the ^ operation. It will now always returns a float.
Fixed !Ptr when Ptr points to a String and !Ptr is the entire expression, as in MoveBytes() where !Ptr is the source pointer.
Added Websocket Service support.
Added more precise timestamps on 'W' sniffing.
Fixed TableFile() with MaxFiles = -2 when no card present at compile time.
Modified the operating system to clear the card LED's when card inserted and no errors. When using CardOut() this was working correctly, but with TableFile(), the green LED remained on after the card was inserted.
Fixed ConstantTable data types (float and double).
Fixed TCP Client Connections setting to handle port numbers greater than 32767.
Fixed EditTable(TableName, Record).
Modifyed ETsz() to not inherit units from source variables like windvector and also to allow user defined units if done with Filednames: Units.
Modified FTPClient() when appending a data file, allow response codes to NLST of 450 or 550 (no directory or file).
Modified DataInterval() so if the Units of DataInterval() is MON (month) and auto allocation of the number of records is specified, seconds per record is set to 30*24*3600 rather than the scan interval of the CallTable() instruction.
Changed the keyboard display realtime data display of floats to show more digits when no digits right of decimal are present.
Fixed editing the constant table to keep comments once edited and to handle more than one constant per line (using : syntax).
Added an optional parameter to TriggerSequence() that enables remote setting of variables to trigger the sequence.
Fixed initializing double variables and constants with non-scalar expressions.
Modified FTPClient() modified to allow for a response of 550 to comeback from the NLST command when appending to a data file, even though 550 is not listed as a legal response to the NLST command in the FTP RFC 959.
Fixed Const As Type = expression when expression is not a simple scalar.
Added a number with 'R' or 'r' suffix is Double precision when declaring a constant as a double.
Added a number with 'F' or 'f' suffix is Floating point single precision when declaring a constant as a float (optional).
Fixed AM25T() in slow sequence in pipeline mode when Reps = 1 and RevDiff was used. The RevDiff was not being done. Also, improve the slice time accuracy when using Reps of 1 and AM25T starts with AM25TChan > 1, to take into account all of the extra clocks to get the AM25T channel to the correct position.
Changed the behavior of the ^ operator to always return a floating point value rather than in some cases an integer.
Added a warning message to SubScan() if the scan interval is not an integral of 100 usec.
Increased the size of the error output for the PC pre-compiler. Use a different buffer than the status table so the table definitions between the PC and the logger will be the same for the association feature to work. The size was increased from 256 to 4096.
Changed TableInfo record number so it is updated when polled via BMP5 so it does not break status client.
Fixed "variable not used" warning with aliases.
Changed operating system so flag reps <- 0 as a compile error for all data table instructions, including Sample().
Changed DNPUpdate() so the datalogger can optionally enable unsolicited data when a new connection is made by the datalogger as a TCP Client.
Changed TCPOpen() when there is a routing error. Changed it so it does not try forever but rather just what the timeout specifies.
Fixed a ETsz() fieldnames issue where a fieldname with _Rso inside was being overwritten with _Rso.
Added support for the CDM_SW12() and CDM_SW5() instructions
Changed keyboard display to split up Settings (general) into Settings (general) and Settings (TCP/IP).
Fixed setting items in the Settings table via the keyboard display that are UINT2_T data type.
Fixed first element of a sampled array to show as array(1) instead of as a scalar.
Changed TableInfo and ConstTable time stamps to update when they are changed instead of when they are monitored.
Changed DNP3 for broadcast packets and control when an unsupported point is selected for control.
Changed DNP3, PC pre-compiler to flag a compile error if the comport is in error.
Fixed SerialOutBlock() and MoveBytes() so they can move or output an entire record or partial record from a data table. I.e., they will successfully cross field boundaries if the number of bytes specified is greater that the starting field size. This is the case only if the number of bytes parameter is not variable.
Removed Niche references.
Changed STATUS_NUMFIELDS to the correct value for all loggers.
Fixed CAO_Offset field in the CR3000.
Modified the parameter list for IPNetPower() (changed 2nd parameter from 2 to 25 and added an optional parameter).
Changed FileOpen() so if it is used in conjunction with the files manager setting, then change the name (if a variable) of the file in the public table also.
Changed functions that are used in conjunction with the Files Manager setting so if a new name is passed in then the variable holding the name is large enough.
Added line number information to the units structure in order to provide line number in compile errors that are detected at completion of compile.
Fixed preserving com1..com4 baudrates through operating system download.
Fixed SDI12Sensor() to allow a response time up to 999 seconds instead of 99 seconds.
Fixed missing Sub crashing compiler; FunctionsPtr was NULL yet was used.
Fixed ApplyAndStart() to be true if non-zero.
Changed SetSetting() and SetStatus() so when they are within any kind of sequence like a subroutine or a function then they will not execute at compile time.
Changed the PC pre-compiler to not flag an error in SerialInRecord() when the comport is SDM-SIO1 based on the number of bytes parameter since it does not know the size allocated by SerialOpen().
Fixed SerialInRecord() so when writing "NAN" into a variable of type String where the destination address is on an odd boundary (as it would be if, for example it is referenced as Destination(1,1,4), the 4th character into the string), then "NAN" would be written starting at 1 character before the specified destination, for example, at Destination(1,1,3) instead of Destination(1,1,4).
Changed UDPDatagram() to queue multiple packets between calls.
Changed UDPDataGram() to queue incoming data up to 20 datagrams before it discards.
Changed FTPClient() in conjunction with the files manager setting (3210) to return the new filename controlled by the files manager setting into the local file name variable.
Changed HTTPGet()/HTTPPost() to insert authorization into the header if the URL parameter is prefaced with username:password@.
Added an optional parameter to IPNetPower() to specify a timeout after inactivity to power back down.
Fixed FTPClient() when getting or putting multiple files.
Changed FTPClient() to allow the NLST command to return 450 ("No such directory or fi.e") when using the optional header function for appending files in the remote.l.
Changed the NL200, NL240 net mask and gateway exchange along with the TCP/IP address.
Fixed setting values in the status or constant table via an RTMC project so security is ignored since the .csipassword file is used instead as the security mechanism.
Changed hidden data tables to allow access via HTTP if the highest security level is authorized.
Fixed UTF-8- character set for http and quote non-printable characters for JSON so KANJI comes through correct.
Changed dns_svr to use DeviceConfig setting (domain_name) as the domain name to which it will respond (rather than hard-coded to model.com).
Added code to handle a DHCP renewal request. Art changed the DHCP lease time to 30 seconds and added the function joined_networks() to look through the DHCP cache and see if there are any clients in it that haven't timed out.
Changed sniff(w) and talk through(p) terminal commands to not have timeouts when connected via PakBus.
Changed Constant Table so if editing in the terminal and it fails, display a failure message of ‘out of space’.
Fixed warning message when get or sending variables via PakBus but the packet will not fit into a PakBus frame.
Changed Get/Set Variables to allow swath parameter to be variable.
Changed PakBus directory response so it accommodates a '/' character instead of the ':' character in a file specification. This allows older LoggerNet versions to work that mistakenly replaced the colon with the forward slash character.
Fixed GetDataRecord(), GetFile() and SendFile() so the expression function is not called erroneously, possibly resulting in an out of bounds warning and/or in rare cases a variable set erroneously.
Fixed GetDataRecord() to start at the current record number in the event of reset and maximum records is negative (collect all data).
Fixed a data collect bug where data was written beyond the end of the holding buffer. A call to FindRecord() was requesting too much data. This affected non-interval data tables with small (<= 8 bytes) record sizes.
Modified GPS for setting clock with no PPS signal.
Extended timeout for file upload (including table definitions upload) to 5 minutes.
Changed error code for file upload to return an error code of 9 if there is a fragment offset error instead of 13.
Added TCP ModBus-PakBus DataGram routing.
Enhanced RTU ModBus-PakBus DataGram routing.
Changed FTPUserName and FTPPassword settings so these settings are now accessible via CRBasic and the keyboard display.
Added DNS setting via keyboard display.
Fixed IP trace code reading via CRBasic or keyboard display.
Fixed TLS Status on the keyboard and via CRBasic and remotely.
Fixed some issues with Files Manager setting for sniffing and IP Tracing when changing the maximum file size and also when the file size is very small.
Added pointer type casting that will ensure floating point operations will not truncate to integers.
Enhanced operating system so double numbers must be "forced" using the 'L' or 'l' character at the end of the number.
Fixed a problem with re-assigning a pointer.
Changed CRBasic pointer method such that once a pointer variable is assigned to point to a variable, it can never be 0, i.e., 0 would be an out of bounds, illegal pointer that can be detected by the program.
Fixed ! (pointer) pointing to a variable of type String.
Fixed Pointer = @(Setting) where variable reference by setting is an array of type string.
Fixed the compiler to allow a reference to tablename.fieldname() to act the same as tablename.fieldname.
Fixed CRBasic to flag an error if an assignment statement tries to assign a new value to a constant string.
Added UDP IPv6 support.
Added option 24 to the CheckSum() function for a 16 bit Fletcher checksum.
Added a check for the maximum number of tables that can be used with Tablefile(), which is currently set to 30.
Added a check for duplicate file names when using TableFile().
Fixed PC pre-compiler when it needs declarations before any code.
Fixed DataTableInfo when its size is larger than all other tables for buffer used by findrecord() during data collection.
Fixed ConstTable setting MaxNumBytes (size of memory to allocate for data storage). If any table was larger than the Status table, and there was a ConsTable, the buffer was not large enough to store data into.
Fixed units for WindVector() output options 3 and 4.
Fixed a PC pre-compiler crash when not able to find a specific settings.field.
Change the Rx timeout calculation when changing baud rate. Give at least 35 bit periods to conform to Modbus.
Fixed SMTP via IPv6 to look for the port number after ]:port.
Changed CheckDataGram(service) so it takes care of service.
Fixed ModBus datagram and multiple TCP Modbus within a single packet.
Fixed Replace() when the SearchString string is NULL.
Fixed EmailReceive() using APOP authorization. The server includes this capability in its greeting, not in its CAPA list.
Fixed BroadCast() to not use uninitialized variables.
Changed throttling down PakBus client communication when the comport mailbox is backed up to limit it to no more than 4 in the queue or a 5 second timeout.
Checked sndmsg() for failure in the event we need to release communications memory.
Change the subclass from 0x20 to 0x02. This allows Windows 10 to load the usbser.sys driver without a .inf file.
Increased the requested current limit from 200 to 300.
Modified DNP3 waiting for unsolicited response confirmation will always service a read request.
FileManage changed so changing attribute hidden does not update the directory information if the attribute is already set. This was found when a customer was hiding a file unconditionally in a 10 second scan and destroyed flash chips after ~1.5 years.
Added little Endian support for Ping().
Changed the password settings via the keyboard display and remote access so they are hidden with "..." notation.
Fixed GetDataRecord() when table is interval driven and there are multiple frames per request. An erroneous response code of either 8 or 9 was returned sometimes.
Modified the code when receiving a one way table definitions command to not respond with a no type error response.
Fixed GetDataRecord() and AcceptDataRecord() in the case where the table they are storing into has DataInterval() with 0 lapses.
Fixed PakBus client instructions via TCP when the socket handle number mod 256 is within the range of COM1..COM4 (4..7 in a CR1000, 4..11 in a CR6), causing them to erroneously return -10 for a response code.
Fixed seconds per record output in 'O' command.
Fixed SC115 file hiding.
Fixed validate_query_name to use case insensitive string compare.
Allowed access to hidden data tables via HTTP if the highest security level is authorized.
Disabled SHA256 encryption for the CR1000, CR800, and CR3000 in order to save code space.
Removed Com3 and Com4 from pre-defined constants for the CR800.
Fixed the CRBasic PC pre-compiler so it no longer flags an error in SerialInRecord() when the comport is SDM-SIO1 based on the number of bytes parameter because it does not know the size allocated by SerialOpen().
Removed settings from the keyboard display settings that are not applicable for the CR8X0.
Fixed type casting constants.
Changed security policy related to set value actions over HTTP directed at the Status or ConstTable. Permissions are solely taken from .csipasswd now. Traditional BMP three level security codes are not considered or used.
Fixed possible lockup in file system if FAT is corrupted.
TableFile 64 mode changed to close input file and output new TOB3 file when the Tablefile() output fails. This fixes a problem when the disk fills up in ring mode. This was already fixed in OS 28.02 for non CR6 dataloggers.
Increased the number of allowed user-defined DataTables from 30 to more than 250. The datalogger may now have a maximum of 255 tables, including system tables such as Public, Status, DataTableInfo, CPIStatus, and ConstTable. This feature was already added in OS 28.02 for non CR6 dataloggers.
Changed items to accommodate up to 255 tables. Public Table is now an int instead of char. Bumped the maximum scroll menu size to 256 lines from 100. Removed the start value maximum of 72 on scrolling.
Added keyboard display menu option that allows user to copy table data to a file on the USB or CRD drives. Located under Data-Final Storage Data-Copy Data To CRD
USB. This feature is used for PC-less collection of data, for example when using a CR1000KD and a SC115, without requiring the use of TableFile.
Enhanced compiler so an error is reported when an invalid ComPort is specified for DNP()
Fixed PC compiler crash that was caused by calling a missing sub-routine. FunctionPtr was null yet used.
Fixed PC compiler crash caused by an unhandled Case() occurring outside of Select().