Archived Forum Post

Index of archived forum posts

Question:

Any way to get LESS verbose LastErrorText?

Dec 08 '14 at 05:22

Hi,

I appreciate the verbosity of the LastErrorText showing the stack trace and all associated details. I understand that when reporting a bug to you it is very useful to have that.

However I'd like the option to obtain only the relevant error message for the particular problem at hand. For example when a user tries to send an email, they might have an error of "Server not found" or "invalid username" - which is simply a user error. However when trapping the error in the program I receive a LastErrorText that contains a colossal 30+ lines of information. Presenting all that information to the user is incredibly confusing for them. Even I have to sift through the text to see the actual issue.

So it would be great if I could retrieve just the error message itself, without all the stack trace info. Perhaps a different property such as "LastErrorTextShort", or even an option to set the "ErrorModeVerbose" to false if desired.

Again, not saying the verbose LastErrorText is bad, simply asking for an option to turn it off.


Accepted Answer

We have similar problems (especially as Gmail responses contain specific information that users should see). I have been having a quick look and mailman.LastErrorXml looks useful. At least the fields are sensibly delimited and can be parsed for error info. I agree a more user friendly approach would be better. NB XML seems to get messed up in this post so you may need to try it for your self to see the text. ?mailman.LastErrorXml

<ChilkatLog>
  <VerifyPopLogin>
    <DllDate>Aug  1 2014</DllDate>
    <ChilkatVersion>9.5.0.43</ChilkatVersion>
    <UnlockPrefix>CSensoryMAIL</UnlockPrefix>
    <Username>RWSNOTE05:rob_000</Username>
    <Architecture>Little Endian; 32-bit</Architecture>
    <Language>ActiveX</Language>
    <VerboseLogging>0</VerboseLogging>
    <idleTimeoutMs>30000</idleTimeoutMs>
    <connectTimeoutMs>30000</connectTimeoutMs>
    <Timestamp-1>12:11:41.260</Timestamp-1>
    <Timestamp-2>12:11:41.291</Timestamp-2>
    <pop3OpenConnection>
      <info>Connecting to POP3 server</info>
      <hostname>pop.gmail.com</hostname>
      <port>995</port>
      <ssl>1</ssl>
      <connectTimeoutMs>30000</connectTimeoutMs>
      <socket2Connect>
        <connect2>
          <connectImplicitSsl>
            <clientHandshake>
              <clientHandshake2>
                <processHandshakeRecord>
                  <processHandshakeMessage>
                    <processServerHello>
                      <HelloExtension>renegotiation_info</HelloExtension>
                      <HelloExtensionLen>1</HelloExtensionLen>
                    </processServerHello>
                  </processHandshakeMessage>
                </processHandshakeRecord>
              </clientHandshake2>
            </clientHandshake>
            <checkServerCert>
              <info>Not verifying server certificate...</info>
              <info>Set the RequireSslCertVerify property to enable verification.</info>
            </checkServerCert>
            <info>Secure Channel Established.</info>
          </connectImplicitSsl>
        </connect2>
      </socket2Connect>
      <info>Connected to POP3 server</info>
      <socketOptions>
        <SO_SNDBUF>65536</SO_SNDBUF>
        <SO_RCVBUF>65536</SO_RCVBUF>
        <TCP_NODELAY>1</TCP_NODELAY>
      </socketOptions>
      <PopCmdResp>+OK Gpop eady for requests from 82.71.31.100 u9mb48369784wjw</PopCmdResp>
      <greeting>+OK Gpop ready for requests from 82.71.31.100 u9mb48369784wjw</greeting>
      <ConnectionType>SSL/TLS</ConnectionType>
    </pop3OpenConnection>
    <Pop3Authenticate>
      <username>smartboxtest@gmail.com</username>
      <popSPA>0</popSPA>
      <PopCmdSent>USER xxxxx@gmail.com</PopCmdSent>
      <PopCmdResp>+OK send PASS</PopCmdResp>
      <PopCmdSent>PASS ****</PopCmdSent>
      <PopCmdResp>-ERR [AUTH] Username and password not accepted.</PopCmdResp>
      <error>POP3 response indicates failure.</error>
      <PASS_response><![CDATA[-ERR [AUTH] Username and password not accepted.
]]></PASS_response>
      <info>Check to see if captcha is unlocked on your GMail account.</info>
      <info>See the information at http://www.cknotes.com/?p=370</info>
      <error>POP3 authentication failed</error>
    </Pop3Authenticate>
    <error>Authentication failed.</error>
    <Timestamp-3>12:11:43.151</Timestamp-3>
    <verifyPopLogin>Elapsed time: 1860 millisec</verifyPopLogin>
    <error>Failed.</error>
  </VerifyPopLogin>
</ChilkatLog>

Answer

I do not agree. First of all my understanding is that the LastError* methods are for debugging / internal error tracking only. They are not supposed to be presented to the end user (correct me if I am wrong, Matt, otherwise I tend to agree with the other guys).

Verbose logging is default disabled in all components, but I guess you mean less verbose than non-verbose?

There are already other methods in some (or all?) components for getting an error code instead, e.g. ConnectFailReason in Ftp2. Using those error codes, you can write your own meaningful error messages, that could also be adapted to the end user's language preference. This is way better than letting the library writer decide what to write as an error message, e.g. does "DNS lookup failed" make more or less sense to the non-technical end user than "Failed to resolve ftp server host name" or "Ftp server host name appears to be invalid, please verify the host name and that you have an active Internet connection"?

Sure it would be nice to have a library handle all this stuff, but I prefer to build these error messages myself and can sleep better at night, knowing that Chilkat value the time spent on stabilizing components instead of struggling with meaningful error messages, etc.


Answer

I agree.

Perhaps even better if the current LastErrorText was changed to something like

**Problem: Failed to read initial server version string**
ChilkatLog:
  Connect_SFtp:
    DllDate: Oct  1 2014
    ChilkatVersion: 9.5.0.44
    UnlockPrefix: xxxxx
    Username: DELL7:SYSTEM
    Architecture: Little Endian; 64-bit
    VerboseLogging: 0
    SftpVersion: 3
    hostname: ftp.server.net
    port: 22
    Established TCP/IP connection with SSH server
    clientIdentifier: SSH-2.0-PuTTY_Local:_May_11_2009_17:22:38
    Sending client identifier...
    Done sending client identifier.
    Reading server version...
    Failed to read initial server version string
    bytesReceived:
    Failed.
  --Connect_SFtp
--ChilkatLog

so the (most likely) issue is listed as the first line.


Answer

Hi roan98dk,

Your understanding of LastErrorText is certainly different from mine. Can you kindly explain what is the alternative? There is no other source of error information that I'm aware of. All of the example code I've seen includes reporting LastErrorText when an error occurs.

Let's take an example. In my program users can send email. If, for example, they entered the wrong SMTP server in their settings and then try to send an email, I could either:

a) Inform them that the email could not be sent, with no further information. (Not very useful to anyone).

or

b) Give them the LastErrorText info, as that is the only info I with details about the problem. This however means I get this:

ChilkatLog: SendEmail: DllDate: Jul 24 2014 ChilkatVersion: 9.5.0.42 UnlockPrefix: CRUNCHMAILQ Username: THEOLDBOX:George Architecture: Little Endian; 32-bit Language: ActiveX VerboseLogging: 0 recipients: TO: someone@microbase.com.au totalCount: 1 --recipients renderToMime: createEmailForSending: xSigningAlg: sha1 Auto-generating Message-ID --createEmailForSending renderToMime: Elapsed time: 0 millisec --renderToMime progressTotal: 601 smtpConnect: SmtpHost: mail.optusnet.com.au2 SmtpPort: 25 SmtpUsername: SmtpSsl: 0 StartTLS: 0 SmtpConnect: Need new SMTP connection No SMTP login provided. No SMTP password provided. Skipping SMTP authentication because no login/password provided. checkForExistingConnection: Elapsed time: 0 millisec Connecting to SMTP server mail.optusnet.com.au2:25 smtp_host: mail.optusnet.com.au2 smtp_port: 25 smtp_user: NULL auth-method: NONE socket2Connect: connect2: connectSocket: connect_ipv6_or_ipv4: resolveHostname6: getAddressInfo: Failed to get host address info. (3) SocketError: WSAHOST_NOT_FOUND No such host is known. hostOrIpAddr: mail.optusnet.com.au2 port: 25 Versions of Windows earlier than Windows XP are limited to handling IPv4 only On Windows Server 2003 and Windows XP, IPv6 addresses are returned only if IPv6 is installed on the local computer. --getAddressInfo --resolveHostname6 Domain to IP address resolution failed. --connect_ipv6_or_ipv4 --connectSocket ConnectFailReason: DNS lookup failed --connect2 --socket2Connect Failed to connect to SMTP server. --SmtpConnect checkOrMakeSmtpConnection: Elapsed time: 157 millisec --smtpConnect Failed. --SendEmail --ChilkatLog .

Now in there is the problem - No such host is known. But it's buried in a mountain of other technical stack trace info that is no use to an end user. The message is so large that it has to be scrolled through in a textbox.

So again I invite you to share with me the alternative error information that I'm not aware of. Also explain how that would be considered "non-verbose". I've never used any component that provides that much error message before.


Answer

Chilkat posted a blog quite a while ago about diagnosing SMTP failures. I use a similar approach as suggested by Chilkat.

I can't deny that it would be nice to have a method similar to the connectFailReason property of Ftp2 in MailMan. Then a simple return code will tell you if the DNS lookup failed, timed out, login failed, etc. Currently you will have to use the LastSmtpStatus, the Verify methods and perhaps even Socket's DnsLookup() or parse the LastError returned. If the most probable cause of failure is always part of LastError*, then it ought to be possible to create and error code matrix instead (or in addition).

BTW, I do not mind that an actual error message is also returned for those that do not want to struggle with customized error messages, e.g. SFtp has a DisconnectCode but also a DisconnectReason property.

Actually this entire matter raises a lot of questions and thoughts and actually writing this response took me at least an hour, simply because it got me thinking about whether it it even possible to implement a generic way of returning both a simple error code (LastErrorCode?) and short error text (LastErrorReason?) in all relevant Chilkat components (plus my daughter kept disturbing me ;-)

Chilkat (Matt): Do you have any comments on this matter?


Answer

I understand everything everybody is saying, and if it were a simple task, then it would've already been done. Internal to Chilkat there are many different layers and subsystems: sockets, TLS, encryption, MIME, proxies, character encoding, compression, digital signatures, XML, protocol layers, authentication, etc. Should the error at the lowest level (i.e. the 1st error encountered) be the simple error? If so, it would be virtually meaningless. (For example, failing to read a socket, or timing out on a socket read is meaningless unless you know the context and what it was trying to do within the higher-level protocol, such as SMTP or FTP) What about error messages returned by the underlying operating system, such as "WSAHOST_NOT_FOUND No such host is known" -- there are an infinite possibilities across many different operating systems. Which ones are meaningful and which not? You can't even enumerate all of them because they are unknown.

Should the simple error message begin at a lower level (within Chilkat) and then potentially be superceded at a higher level? Some cases might make sense, others wouldn't. Would this have to be done for the entire Chilkat library at once? This would be a very large task. There are many other customers demanding many other things. What is most important? Would customers like new products instead? Or perhaps an async version of every Chilkat method that can possibly take time (such as what was done for the Chilkat for Windows Store released just now)? What is best long-term for Chilkat the company, in terms of revenue and survival? (Don't worry, revenue is fine, but longer-term vision must always be present.)

I'm still thinking about the issue. Should the approach be comprehensive, or piecemeal? I don't know, except I do know that in many cases, a single error message will be virtually meaningless and unhelpful. One idea might be to "lay the piping" and then incrementally add the simple (summary) error messages over time so that it's not one giant project -- but where the most critical/common ones are added first and then others are filled in as complaints arise or as noticed.


Answer

Thanks for your reply, I appreciate the complexities of the issue.

I believe your current approach to error reporting can be left intact. The requirement I see is simply to be able to obtain only the error related info in LastErrorText.

Idea 1: When error messages are added to the LastErrorText they are delimited in some way. This would allow them to be parsed from the overall body, if desired.

Idea 2: Create a new property such as SimpleErrorText. It contains only those strings that relate to error responses or codes. In the event that there were no errors, it would be empty. In this case LastErrorText would remain unchanged.


Answer

I just wanted to add that I still believe that as much as possible error/status codes should be used. However I also recognize that there are cases where the error message returned by the server cannot easily be converted to a simple code. The example with Google's CAPTCHA response is a perfect example of where the error message should be returned to the client without all of the surrounding log.

The question is whether it is safe to assume that some services will always follow standards and return a proper status code? I am afraid that that is not the case very often. An example could perhaps be a return code of 301 from an FTP server, which refers to a login failure. Would it be safe to ask the user to simply verify username and password or might the server return valuable text message as well, e.g. "The account has been banned!"? In that case it might make little sense to tell the user to verify credentials only. Still the message is not the best. Do all users understand what banned means? Sure we could wrap this in a longer message including both the response from the server and a reference to our troubleshooting guide.