One place for hosting & domains

      Errors

      How to Add Extra Information to Errors in Go


      The author selected the Diversity in Tech Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      When a function in Go fails, the function will return a value using the error interface to allow the caller to handle that failure. In many cases, developers will use the fmt.Errorf function in the fmt package to return these values. Prior to Go 1.13, though, a downside of using this function is that you would lose information about any errors that may have caused the error to be returned. To solve this, developers would either use packages to provide a way to “wrap” errors inside other errors or create custom errors by implementing the Error() string method on one of their struct error types. Sometimes it can be tedious to create these struct types if you have a number of errors that don’t need to be handled explicitly by the callers, though, so in Go 1.13, the language added features to make it easier to handle these cases.

      One feature is the ability to wrap errors using the fmt.Errorf function with an error value that can be unwrapped later to access the wrapped errors. This builds the error-wrapping functionality into the Go standard library, so there’s no longer any need to use a third-party library.

      Additionally, the functions errors.Is and errors.As make it easier to determine if a specific error is wrapped anywhere inside a given error, and will also give you access to that specific error directly without needing to unwrap all the errors yourself.

      In this tutorial, you’ll create a program that uses these functions to include additional information in errors returned from your functions, and then create your own custom error struct that supports the wrapping and unwrapping functionality.

      Prerequisites

      Returning and Handling Errors in Go

      When an error occurs in a program, it’s good practice to handle those errors so your users never see them — but to handle the errors, you need to know about them first. In Go, you can handle errors in your program by returning information about the error from your functions using a special interface type, the error interface. Using the error interface allows any Go type to be returned as an error value as long as that type has an Error() string method defined. The Go standard library provides functionality to create errors for these return values, such as the fmt.Errorf function.

      In this section, you’ll create a program with a function that uses fmt.Errorf to return an error, and you will also add an error handler to check for the errors that the function could return. (If you’d like more information on handling errors in Go, please see the tutorial, Handling Errors in Go.)

      Many developers have a directory to keep current projects. In this tutorial, you’ll use a directory named projects.

      To begin, make the projects directory and navigate to it:

      • mkdir projects
      • cd projects

      From the projects directory, create a new errtutorial directory to keep the new program in:

      Next, navigate into the new directory with the cd command:

      Once you’re in the errtutorial directory, use the go mod init command to create a new module named errtutorial:

      After creating the Go module, open a file named main.go in the errtutorial directory using nano, or your favorite editor:

      Next, you will write a program. The program will loop over the numbers 1 through 3 and try to determine if those numbers are valid or not using a function called validateValue. If the number is determined to be invalid, the program will use the fmt.Errorf function to generate an error value that is returned from the function. The fmt.Errorf function allows you to create an error value where the error message is the message you provide to the function. It works similarly to fmt.Printf, but instead of printing the message to the screen it returns it as an error instead.

      Then, in the main function, the error value will be checked to see if it’s a nil value or not. If it is a nil value, the function succeeded and the valid! message is printed. If it’s not, the error received is printed instead.

      To begin your program, add the following code into your main.go file:

      projects/errtutorial/main.go

      package main
      
      import (
          "fmt"
      )
      
      func validateValue(number int) error {
          if number == 1 {
              return fmt.Errorf("that's odd")
          } else if number == 2 {
              return fmt.Errorf("uh oh")
          }
          return nil
      }
      
      func main() {
          for num := 1; num <= 3; num++ {
              fmt.Printf("validating %d... ", num)
              err := validateValue(num)
              if err != nil {
                  fmt.Println("there was an error:", err)
              } else {
                  fmt.Println("valid!")
              }
          }
      }
      

      The validateValue function from the program takes a number and then returns an error based on whether it was determined to be a valid value or not. In this program, the number 1 is invalid and returns the error that's odd. The number 2 is invalid and returns the error uh oh. The validateValue function uses the fmt.Errorf function to generate the error value being returned. The fmt.Errorf function is convenient for returning errors because it allows you to format an error message using formatting similar to fmt.Printf or fmt.Sprintf without needing to then pass that string to errors.New.

      In the main function, the for loop will start by iterating over each number from 1 to 3 and will store the value in the num variable. Inside the loop body, a call to fmt.Printf will print the number the program is currently validating. Then, it will call the validateValue function and pass in num, the current number being validated, and store the error result in the err variable. Lastly, if err is not nil it means an error occured during validation and the error message is printed using fmt.Println. The else clause of the error check will print "valid!" when an error wasn’t encountered.

      After saving your changes, run your program using the go run command with main.go as the argument from the errtutorial directory:

      The output from running the program will show that validation was run for each number and number 1 and number 2 returned their appropriate errors:

      Output

      validating 1... there was an error: that's odd validating 2... there was an error: uh oh validating 3... valid!

      When you look at the output from the program, you’ll see the program tried to validate all three numbers. The first time it says the validateValue function returned the that's odd error, which would be expected for the value of 1. The next value, 2, also shows it returned an error, but it was the uh oh error this time . Finally, the 3 value returns nil for the error value, meaning there wasn’t an error and the number is valid. The way the validateValue function is written, the nil error value would be returned for any values that aren’t either 1 or 2.

      In this section, you used fmt.Errorf to create error values you returned from a function. You also added an error handler to print out the error message when any error is returned from the function. At times, though, it can be useful to know what an error means, not just that an error occurred. In the next section, you’ll learn to customize error handling for specific cases.

      Handling Specific Errors Using Sentinel Errors

      When you receive an error value from a function, the most basic error handling is to check if the error value is nil or not. This will tell you if the function had an error, but sometimes you may want to customize error handling for a specific error case. For example, imagine you have code connecting to a remote server, and the only error information you get back is “you had an error”. You may wish to tell whether the error was because the server was unavailable or if your connection credentials were invalid. If you knew the error meant a user’s credentials were wrong, you might want to let the user know right away. But if the error means the server was unavailable, you may want to try reconnecting a few times before letting the user know. Determining the difference between these errors allows you to write more robust and user-friendly programs.

      One way you could check for a particular type of error might be using the Error method on an error type to get the message from the error and compare that value to the type of error you’re looking for. Imagine that in your program, you want to show a message other than there was an error: uh oh when the error value is uh oh. One approach to handling this case would be to check the value returned from the Error method, like so:

      if err.Error() == "uh oh" {
          // Handle 'uh oh' error.
          fmt.Println("oh no!")
      }
      

      Checking the string value of err.Error() to see if it’s the value uh oh, as in the code above, would work in this case. But the code would not work if the uh oh error string is slightly different elsewhere in the program. Checking errors this way can also lead to significant updates to code if the error’s message itself needs to be updated because every place the error is checked would need to be updated. Take the following code, for example:

      func giveMeError() error {
          return fmt.Errorf("uh h")
      }
      
      err := giveMeError()
      if err.Error() == "uh h" {
          // "uh h" error code
      }
      

      In this code, the error message includes a typo and is missing the o in uh oh. If this is noticed and fixed at some point, but only after adding this error checking in several places, all those places will need to have their checks updated to err.Error() == "uh oh". If one is missed, which could be easy because it’s only a single character change, the expected custom error handler will not run because it’s expecting uh h and not uh oh.

      In cases like these, where you may want to handle a specific error differently than others, it’s common to create a variable whose purpose is to hold an error value. This way, the code can check against that variable instead of a string. Typically, these variables begin with either err or Err in their names to signify they’re errors. If the error is only meant to be used within the package it’s defined in, you would want to use the err prefix. If the error is meant to be used elsewhere, you would instead use the Err prefix to make it an exported value, similar to a function or a struct.

      Now, let’s say you were using one of these error values in the typo example from before:

      var errUhOh = fmt.Errorf("uh h")
      
      func giveMeError() error {
          return errUhOh
      }
      
      err := giveMeError()
      if err == errUhOh {
          // "uh oh" error code
      }
      

      In this example, the variable errUhOh is defined as the error value for an “uh oh” error (even though it’s misspelled). The giveMeError function returns the value of errUhOh because it wants to let the caller know that an “uh oh” error happened. Then, the error handling code compares the err value returned from giveMeError against errUhOh to see if an “uh oh” error is the one that happened. Even if the typo is found and fixed, all the code would still be working because the error check is checking against the value of errUhOh, and the value of errUhOh is the fixed version of the error value that giveMeError is returning.

      An error value that is intended to be checked and compared in this way is known as a sentinel error. A sentinel error is an error that’s designed to be a unique value that can always be compared against for a specific meaning. The errUhOh value above will always have the same meaning, that an “uh oh” error occurred, so a program can rely on comparing an error to errUhOh to determine whether that error occurred.

      The Go standard library also defines a number of sentinel errors that are available when developing Go programs. One example would be the sql.ErrNoRows error. The sql.ErrNoRows error is returned when a database query doesn’t return any results, so that error can be handled differently from a connection error. Since it’s a sentinel error, it can be compared against in error-checking code to know when a query doesn’t return any rows, and the program can handle that differently than other errors.

      Generally, when creating a sentinel error value, the errors.New function from the errors package is used instead of the fmt.Errorf function you’ve been using thus far. Using errors.New instead of fmt.Errorf does not make any foundational changes to how the error works, though, and both functions could be used interchangeably most of the time. The biggest difference between the two is the errors.New function will only create an error with a static message and the fmt.Errorf function allows formatting the string with values, similar to fmt.Printf or fmt.Sprintf. Since sentinel errors are fundamental errors with values that don’t change, it’s common to use errors.New to create them.

      Now, update your program to use a sentinel error for the “uh oh” error instead of fmt.Errorf.

      First, open the main.go file to add the new errUhOh sentinel error and update the program to use it. The validateValue function is updated to return the sentinel error instead of using fmt.Errorf. The main function is updated to check for the errUhOh sentinel error and print oh no! when it encounters it instead of the there was an error: message it shows for other errors.

      projects/errtutorial/main.go

      package main
      
      import (
          "errors"
          "fmt"
      )
      
      var (
          errUhOh = errors.New("uh oh")
      )
      
      func validateValue(number int) error {
          if number == 1 {
              return fmt.Errorf("that's odd")
          } else if number == 2 {
              return errUhOh
          }
          return nil
      }
      
      func main() {
          for num := 1; num <= 3; num++ {
              fmt.Printf("validating %d... ", num)
              err := validateValue(num)
              if err == errUhOh {
                  fmt.Println("oh no!")
              } else if err != nil {
                  fmt.Println("there was an error:", err)
              } else {
                  fmt.Println("valid!")
              }
          }
      }
      

      Now, save your code and use go run to run your program again:

      This time the output will show the generic error output for the 1 value, but it uses the custom oh no! message when it sees the errUhOh error returned from validateValue for 2:

      Output

      validating 1... there was an error: that's odd validating 2... oh no! validating 3... valid!

      Using sentinel errors inside your error checking makes it easier to handle special error cases. For example, they can help determine whether the file you’re reading is failing because you’ve reached the end of the file, which is signified by the io.EOF sentinel error, or if it’s failing for some other reason.

      In this section, you created a Go program that uses a sentinel error using errors.New to signify when a specific type of error occurred. Over time as your program grows, though, you may get to the point where you’d like more information included in your error than just the uh oh error value. This error value doesn’t give any context on where the error happened or why it happened, and it can be hard to track down specifics of the error in larger programs. To aid in troubleshooting and to cut down the time for debugging, you can make use of error wrapping to include the specifics you need.

      Wrapping and Unwrapping Errors

      Wrapping errors means taking one error value and putting another error value inside it, like a wrapped gift. Similar to a wrapped gift, though, you need to unwrap it to know what’s inside. Wrapping an error allows you to include additional information about where the error came from or how it happened without losing the original error value, since it’s inside the wrapper.

      Before Go 1.13, it was possible to wrap errors since you could create custom error values that included the original error. But you would either have to create your own wrappers or use a library that already did the work for you. In Go 1.13, though, Go added support for wrapping and unwrapping errors as part of the standard library by adding the errors.Unwrap function and the %w verb for the fmt.Errorf function. In this section, you’ll update your program to use the %w verb to wrap errors with more information, and you’ll then use errors.Unwrap to retrieve the wrapped information.

      Wrapping Errors with fmt.Errorf

      The first feature to examine when wrapping and unwrapping errors is an addition to the existing fmt.Errorf function. In the past, fmt.Errorf was used to create formatted error messages with additional information using verbs such as %s for strings and %v for generic values. Go 1.13 added a new verb with a special case, the %w verb. When the %w verb is included in a format string and an error is provided for the value, the error returned from fmt.Errorf will include the value of the error wrapped in the error being created.

      Now, open the main.go file and update it to include a new function called runValidation. This function will take the number currently being validated and run any validation needed on that number. In this case, it only needs to run the validateValue function. If it encounters an error validating the value it will wrap the error using fmt.Errorf and the %w verb to show there was a run error that occurred, then return that new error. You should also update the main function so instead of calling validateValue directly it calls runValidation instead:

      projects/errtutorial/main.go

      
      ...
      
      var (
          errUhOh = errors.New("uh oh")
      )
      
      func runValidation(number int) error {
          err := validateValue(number)
          if err != nil {
              return fmt.Errorf("run error: %w", err)
          }
          return nil
      }
      
      ...
      
      func main() {
          for num := 1; num <= 3; num++ {
              fmt.Printf("validating %d... ", num)
              err := runValidation(num)
              if err == errUhOh {
                  fmt.Println("oh no!")
              } else if err != nil {
                  fmt.Println("there was an error:", err)
              } else {
                  fmt.Println("valid!")
              }
          }
      }
      

      Once you’ve saved your updates, run the updated program using go run:

      The output will look similar to this:

      Output

      validating 1... there was an error: run error: that's odd validating 2... there was an error: run error: uh oh validating 3... valid!

      There are a few things to look at in this output. First, you’ll see the error message being printed for the value 1 now includes run error: that's odd in the error message. This shows the error was wrapped by runValidation’s fmt.Errorf and that the value of the error being wrapped, that's odd, is included in the error message.

      Next, though, there’s a problem. The special error handling that was added for the errUhOh error isn’t running. If you look at the line validating the 2 input, you’ll see it shows the default error message of there was an error: run error: uh oh instead of the expected oh no! message. You know the validateValue function is still returning the uh oh error because you can see it at the end of the wrapped error, but the error detection of errUhOh is no longer working. This happens because the error being returned by runValidation is no longer errUhOh, it’s the wrapped error created by fmt.Errorf. When the if statement tries to compare the err variable to errUhOh, it returns false because err isn’t equal to errUhOh any more, it’s equal to the error that’s wrapping errUhOh. To fix the errUhOh error checking, you’ll need to retrieve the error from inside the wrapper, using the errors.Unwrap function.

      Unwrapping Errors with errors.Unwrap

      In addition to the %w verb being added in Go 1.13, a few new functions were added to the Go errors package. One of these, the errors.Unwrap function, takes an error as a parameter and, if the error passed in is an error wrapper, it will return the wrapped error. If the error provided isn’t a wrapper, the function will return nil.

      Now, open the main.go file again and, using errors.Unwrap, update the errUhOh error check to handle the case where errUhOh is wrapped inside an error wrapper:

      projects/errtutorial/main.go

      func main() {
          for num := 1; num <= 3; num++ {
              fmt.Printf("validating %d... ", num)
              err := runValidation(num)
              if err == errUhOh || errors.Unwrap(err) == errUhOh {
                  fmt.Println("oh no!")
              } else if err != nil {
                  fmt.Println("there was an error:", err)
              } else {
                  fmt.Println("valid!")
              }
          }
      }
      

      After saving the edits, run the program again:

      The output will look similar to this:

      Output

      validating 1... there was an error: run error: that's odd validating 2... oh no! validating 3... valid!

      Now, in the output, you’ll see the oh no! error handling for the 2 input value is back. The additional errors.Unwrap function call you added to the if statement allows it to detect errUhOh both when err itself is an errUhOh value as well as if err is an error that is directly wrapping errUhOh.

      In this section, you used the %w verb added to fmt.Errorf to wrap the errUhOh error inside another error and give it additional information. Then, you used errors.Unwrap to access the errorUhOh error that is wrapped inside another error. Including errors inside other errors as string values is OK for humans reading error messages, but sometimes you’ll want to include additional information with the error wrapper to aid the program in handling the error, such as the status code in an HTTP request error. When this happens, you can create a new custom error to return.

      Custom Wrapped Errors

      Since Go’s only rule for the error interface is that it includes an Error method, it’s possible to turn many Go types into a custom error. One way is by defining a struct type with extra information about the error, and then also including an Error method.

      For a validation error, it may be useful to know which value actually caused the error. Next, let’s create a new ValueError struct that contains a field for the Value that caused the error and an Err field that contains the actual validation error. Custom error types commonly use the Error suffix on the end of the type name to signify it’s a type that conforms to the error interface.

      Open your main.go file and add the new ValueError error struct, as well as a newValueError function to create instances of the error. You will also need to create a method called Error for ValueError so the struct will be considered an error. This Error method should return the value you want to be displayed whenever the error is converted to a string. In this case, it will use fmt.Sprintf to return a string that shows value error: and then the wrapped error. Also, update the validateValue function so instead of returning just the basic error, it uses the newValueError function to return a custom error:

      projects/errtutorial/main.go

      
      ...
      
      var (
          errUhOh = fmt.Errorf("uh oh")
      )
      
      type ValueError struct {
          Value int
          Err   error
      }
      
      func newValueError(value int, err error) *ValueError {
          return &ValueError{
              Value: value,
              Err:   err,
          }
      }
      
      func (ve *ValueError) Error() string {
          return fmt.Sprintf("value error: %s", ve.Err)
      }
      
      ...
      
      func validateValue(number int) error {
          if number == 1 {
              return newValueError(number, fmt.Errorf("that's odd"))
          } else if number == 2 {
              return newValueError(number, errUhOh)
          }
          return nil
      }
      
      ...
      

      Once your updates are saved, run the program again with go run:

      The output will look similar to this:

      Output

      validating 1... there was an error: run error: value error: that's odd validating 2... there was an error: run error: value error: uh oh validating 3... valid!

      You’ll see that the output now shows the errors are wrapped inside of ValueError by the value error: before them in the output. However, the uh oh error detection is broken again because errUhOh is now inside two layers of wrappers, ValueError and the fmt.Errorf wrapper from runValidation. The code code only uses errors.Unwrap once on the error, so this results in the first errors.Unwrap(err) now only returning a *ValueError and not errUhOh.

      One way to fix this would be to update the errUhOh check to add an additional error check that calls errors.Unwrap() twice to unwrap both layers. To add this, open your main.go file and update your main function to include this change:

      projects/errtutorial/main.go

      
      ...
      
      func main() {
          for num := 1; num <= 3; num++ {
              fmt.Printf("validating %d... ", num)
              err := runValidation(num)
              if err == errUhOh ||
                  errors.Unwrap(err) == errUhOh ||
                  errors.Unwrap(errors.Unwrap(err)) == errUhOh {
                  fmt.Println("oh no!")
              } else if err != nil {
                  fmt.Println("there was an error:", err)
              } else {
                  fmt.Println("valid!")
              }
          }
      }
      

      Now, save your main.go file and use go run to run your program again:

      The output will look similar to this:

      Output

      validating 1... there was an error: run error: value error: that's odd validating 2... there was an error: run error: value error: uh oh validating 3... valid!

      You’ll see that, uh oh, the errUhOh special error handling is still not working. The line validating the 2 input where we’d expect to see the special error handling oh no! output still shows the default there was an error: run error: ... error output. This happens because the errors.Unwrap function doesn’t know how to unwrap the ValueError custom error type. In order for a custom error to be unwrapped, it needs to have its own Unwrap method that returns the inner error as an error value. When creating errors using fmt.Errorf with the %w verb earlier, Go was actually creating an error for you that already has an Unwrap method added, so you didn’t need to do it yourself. Now that you’re using your own custom function, though, you need to add your own.

      To finally fix the errUhOh error case, open main.go and add an Unwrap method to ValueError that returns Err, the field the inner wrapped error is stored in:

      projects/errtutorial/main.go

      
      ...
      
      func (ve *ValueError) Error() string {
          return fmt.Sprintf("value error: %s", ve.Err)
      }
      
      func (ve *ValueError) Unwrap() error {
          return ve.Err
      }
      
      ...
      

      Then, once you’ve saved the new Unwrap method, run your program:

      The output will look similar to this:

      Output

      validating 1... there was an error: run error: value error: that's odd validating 2... oh no! validating 3... valid!

      The output shows the oh no! error handling for the errUhOh error is working again because errors.Unwrap is now able to also unwrap ValueError.

      In this section you created a new, custom ValueError error to provide yourself or your users with information about the validation process as part of the error message. You also added support for error unwrapping to your ValueError so errors.Unwrap can be used to access the wrapped error.

      The error handling is getting a bit clunky and hard to maintain, though. Every time there’s a new layer of wrapping you’ve had to add another errors.Unwrap to the error checking to handle it. Thankfully, the errors.Is and errors.As functions in the errors package are available to make working with wrapped errors easier.

      Working with Wrapped Errors

      If you needed to add a new errors.Unwrap function call for every potential layer of error wrapping your program had, it would get very long and difficult to maintain. For this reason, two additional functions were also added to the errors package in the Go 1.13 release. Both of these functions make it easier to work with errors by allowing you to interact with errors no matter how deeply they’re wrapped inside other errors. The errors.Is function allows you to check if a specific sentinel error value is anywhere inside a wrapped error. The errors.As function allows you to get a reference to a certain type of error anywhere inside a wrapped error.

      Checking an Error Value with errors.Is

      Using errors.Is to check for a specific error makes the errUhOh special error handling much shorter because it handles all the nested error unwrapping you were doing manually. The function takes two error parameters, the first being the error you actually received and the second parameter being the error you want to check against.

      To clean up the errUhOh error handling, open your main.go file and update the errUhOh check in the main function to use errors.Is instead:

      projects/errtutorial/main.go

      
      ...
      
      func main() {
          for num := 1; num <= 3; num++ {
              fmt.Printf("validating %d... ", num)
              err := runValidation(num)
              if errors.Is(err, errUhOh) {
                  fmt.Println("oh no!")
              } else if err != nil {
                  fmt.Println("there was an error:", err)
              } else {
                  fmt.Println("valid!")
              }
          }
      }
      

      Then, save your code and run the program again using go run:

      The output will look similar to this:

      Output

      validating 1... there was an error: run error: value error: that's odd validating 2... oh no! validating 3... valid!

      The output shows the oh no! error message, which means that even though there’s only one error check for errUhOh, it will still be found in the error chain. errors.Is takes advantage of an error type’s Unwrap method to keep digging deeper into a chain of errors until it either finds the error value you’re looking for, a sentinel error, or encounters an Unwrap method that returns a nil value.

      Using errors.Is is the recommended way to check for specific errors now that error wrapping exists as a feature in Go. Not only can it be used for your own error values, but it can also be used for other error values such as the sql.ErrNoRows error mentioned earlier in this tutorial.

      Retrieving an Error Type with errors.As

      The last function added to the errors package in Go 1.13 is the errors.As function. This function is used when you want to get a reference to a certain type of error to interact with it in more detail. For example, the ValueError custom error you added earlier gives access to the actual value being validated in the Value field of the error, but you can only access it if you have a reference to that error first. This is where errors.As comes in. You can give errors.As an error, similar to errors.Is, and a variable for a type of error. It will then go through the error chain to see if any of the wrapped errors match the type provided. If one matches, the variable passed in for the error type will be set with the error errors.As found, and the function will return true. If no error types match, it will return false.

      Using errors.As you can now take advantage of the ValueError type to show additional error information in your error handler. Open your main.go file one last time and update the main function to add a new error handling case for ValueError-type errors that prints out value error, the invalid number, and the validation error:

      projects/errtutorial/main.go

      
      ...
      
      func main() {
          for num := 1; num <= 3; num++ {
              fmt.Printf("validating %d... ", num)
              err := runValidation(num)
      
              var valueErr *ValueError
              if errors.Is(err, errUhOh) {
                  fmt.Println("oh no!")
              } else if errors.As(err, &valueErr) {
                  fmt.Printf("value error (%d): %vn", valueErr.Value, valueErr.Err)
              } else if err != nil {
                  fmt.Println("there was an error:", err)
              } else {
                  fmt.Println("valid!")
              }
          }
      }
      

      In the code above, you declared a new valueErr variable and used errors.As to get a reference to the ValueError if it’s wrapped inside the err value. By getting access to the error as a ValueError, you’re then able to access any additional fields the type provides, such as the actual value that failed validation. This could be helpful if the validation logic happens deeper inside the program and you don’t normally have access to the values to give users hints on where something might have gone wrong. Another example of where this could be helpful is if you’re doing network programming and run into a net.DNSError. By getting a reference to the error, you are able to see if the error was the result of not being able to connect, or if the error was caused by being able to connect, but your resource was not found. Once you know this, you can handle the error in different ways.

      To see errors.As in action, save your file and run the program using go run:

      The output will look similar to this:

      Output

      validating 1... value error (1): that's odd validating 2... oh no! validating 3... valid!

      This time in the output you won’t see the default there was an error: ... message, because all the errors are being handled by other error handlers. The output for validating 1 shows that the errors.As error check returned true because the value error ... error message is being displayed. Since the errors.As function returned true, the valueErr variable is set to be a ValueError and can be used to print out the value that failed validation by accessing valueErr.Value.

      For the 2 value, the output also shows that even though the errUhOh is also wrapped inside a ValueError wrapper, the oh no! special error handler is still executed. This is because the special error handler using errors.Is for errUhOh comes first in the collection of if statements handling the errors. Since this handler returns true before the errors.As even runs, the special oh no! handler is the one executed. If the errors.As in your code came before the errors.Is, the oh no! error message would become the same value error ... as the 1 value, except in this case it would print value error (2): uh oh.

      In this section, you updated your program to use the errors.Is function to remove a lot of additional calls to errors.Unwrap and make your error handling code more robust and future-proof. You also used the errors.As function to check if any of the wrapped errors is a ValueError, and then used fields on the value if one was found.

      Conclusion

      In this tutorial, you wrapped an error using the %w format verb and unwrapped an error using errors.Unwrap. You also created a custom error type that supports errors.Unwrap in your own code. Finally, you used your custom error type to explore the new helper functions errors.Is and errors.As.

      Using these new error functions makes it easier to include deeper information about the errors you create or work with. It also future proofs your code to ensure your error checking continues to work even if errors become deeply nested going forward.

      If you’d like to find more details about how to use the new error features, the Go blog has a post about Working with Errors in Go 1.13. The documentation for the errors package package also includes more information.

      This tutorial is also part of the DigitalOcean How to Code in Go series. The series covers a number of Go topics, from installing Go for the first time to how to use the language itself.



      Source link

      How To Handle Errors in a Flask Application


      The author selected the Free and Open Source Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Flask is a lightweight Python web framework that provides useful tools and features for creating web applications in the Python Language.

      When you’re developing a web application, you will inevitably run into situations where your application behaves in a way contrary to what you expected. You might misspell a variable, misuse a for loop, or construct an if statement in a way that raises a Python exception, like calling a function before declaring it, or simply looking for a page that doesn’t exist. You’ll find it easier and smoother to develop your Flask applications if you learn how to handle errors and exceptions properly.

      In this tutorial, you’ll build a small web application that demonstrates how to handle common errors one encounters when developing a web application. You’ll create custom error pages, use the Flask debugger to troubleshoot exceptions, and use logging to track events in your application.

      Prerequisites

      Step 1 — Using The Flask Debugger

      In this step, you’ll create an application that has a few errors and run it without debug mode to see how the application responds. Then you’ll run it with debug mode on and use the debugger to troubleshoot application errors.

      With your programming environment activated and Flask installed, open a file called app.py for editing inside your flask_app directory:

      Add the following code inside the app.py file:

      flask_app/app.py

      from flask import Flask
      
      app = Flask(__name__)
      
      
      @app.route('/')
      def index():
          return render_template('index.html')
      

      In the above code, you first import the Flask class from the flask package. Then you create a Flask application instance called app. You use the @app.route() decorator to create a view function called index(), which calls the render_template() function as the return value, which in turn renders a template called index.html. There are two errors in this code: the first is that you did not import the render_template() function, and the second one is that the index.html template file does not exist.

      Save and close the file.

      Next, inform Flask about the application using the FLASK_APP environment variable using the following command (on Windows, use set instead of export):

      Then run the application server using the flask run command:

      You will see the following information in your terminal:

      Output

      * Serving Flask app 'app' (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

      This output provides the following information:

      • The Flask application being served (app.py in this case)
      • The environment, which is production here. The warning message stresses that this server is not for a production deployment. You’re using this server for development, so you can ignore this warning, but for more information, see the Deployment Options page on the Flask documentation. You can also check out this Flask deployment tutorial with Gunicorn, or this one with uWSGI, or you can use DigitalOcean App Platform to deploy your Flask application by following the How To Deploy a Flask App Using Gunicorn to App Platform tutorial.

      • The debug mode is off, which means that the Flask debugger is not running, and you won’t receive helpful error messages in your application. In a production environment, displaying detailed errors exposes your application to security vulnerabilities.

      • The server is running on the http://127.0.0.1:5000/ URL. To stop the server, use CTRL+C, but don’t do that just yet.

      Now, visit the index page using your browser:

      http://127.0.0.1:5000/
      

      You will see a message that looks like the following:

      Output

      Internal Server Error The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.

      This is the 500 Internal Server Error, which is a server error response that indicates that the server encountered an internal error in the application code.

      In the terminal, you’ll see the following output:

      Output

      [2021-09-12 15:16:56,441] ERROR in app: Exception on / [GET] Traceback (most recent call last): File "/home/abd/.local/lib/python3.9/site-packages/flask/app.py", line 2070, in wsgi_app response = self.full_dispatch_request() File "/home/abd/.local/lib/python3.9/site-packages/flask/app.py", line 1515, in full_dispatch_request rv = self.handle_user_exception(e) File "/home/abd/.local/lib/python3.9/site-packages/flask/app.py", line 1513, in full_dispatch_request rv = self.dispatch_request() File "/home/abd/.local/lib/python3.9/site-packages/flask/app.py", line 1499, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args) File "/home/abd/python/flask/series03/flask_app/app.py", line 8, in index return render_template('index.html') NameError: name 'render_template' is not defined 127.0.0.1 - - [12/Sep/2021 15:16:56] "GET / HTTP/1.1" 500 -

      The traceback above goes through the code that triggered the internal server error. The line NameError: name 'render_template' is not defined gives the root cause of the problem: the render_template() function has not been imported.

      As you can see here, you have to go to the terminal to troubleshoot errors, which is not convenient.

      You can have a better troubleshooting experience by enabling the debug mode in your development server. To do so, stop the server with CTRL+C and set the environment variable FLASK_ENV to development, so you can run the application in development mode (which enables the debugger), using the following command (on Windows, use set instead of export):

      • export FLASK_ENV=development

      Run the development server:

      You’ll see an output similar to the following in the terminal:

      Output

      * Serving Flask app 'app' (lazy loading) * Environment: development * Debug mode: on * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 120-484-907

      Here you see that the environment is now development, debug mode is on, and the debugger is active. The Debugger PIN is a PIN you need to unlock the console in your browser (an interactive python shell you can access by clicking the little terminal icon encircled in the image below).

      Refresh the index page on your browser and you’ll see the following page:

      The Flask Debugger

      Here, you see the error message displayed in a manner that’s easier to understand. The first heading gives you the name of the Python exception that caused the problem (NameError in this case). The second line gives you the direct reason (render_template() is not defined, which means it’s not imported in this case). Following that, you have the traceback going through the inner Flask code that was executed. Read the traceback from the bottom upward, because the last line in the traceback usually has the most useful information.

      Note:
      The circled terminal icon allows you to run Python code in the browser on different frames. This is useful for when you want to check the value of a variable the way you would do it in a Python interactive shell. When you click the terminal icon, you will need to type in the Debugger PIN code you got when you ran the server. You won’t need this interactive shell in this tutorial.

      To fix this NameError issue, leave the server running, open a new terminal window, activate your environment, and open your app.py file:

      Modify the file to look as follows:

      flask_app/app.py

      
      from flask import Flask, render_template
      
      app = Flask(__name__)
      
      
      @app.route('/')
      def index():
          return render_template('index.html')
      

      Save and close the file.

      Here you imported the render_template() function that was missing.

      With the development server running, refresh the index page on your browser.

      This time you’ll see an error page with information that looks like so:

      Output

      jinja2.exceptions.TemplateNotFound jinja2.exceptions.TemplateNotFound: index.html

      This error message indicates that the index.html template does not exist.

      To fix this, you’ll create a base.html template file other templates will inherit from to avoid code repetition, then an index.html template that extends the base template.

      Create the templates directory, which is the directory where Flask looks for template files. Then open a base.html file using your favorite editor:

      • mkdir templates
      • nano templates/base.html

      Add the following code to your base.html file:

      flask_app/templates/base.html

      
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>{% block title %} {% endblock %} - FlaskApp</title>
          <style>
              nav a {
                  color: #d64161;
                  font-size: 3em;
                  margin-left: 50px;
                  text-decoration: none;
              }
          </style>
      </head>
      <body>
          <nav>
              <a href="https://www.digitalocean.com/community/tutorials/{{ url_for('index') }}">FlaskApp</a>
              <a href="#">About</a>
          </nav>
          <hr>
          <div class="content">
              {% block content %} {% endblock %}
          </div>
      </body>
      </html>
      

      Save and close the file.

      This base template has all the HTML boilerplate you’ll need to reuse in your other templates. The title block will be replaced to set a title for each page, and the content block will be replaced with the content of each page. The navigation bar has two links, one for the index page where you use the url_for() helper function to link to the index() view function, and the other for an About page if you choose to include one in your application.

      Next, open a template file called index.html, which will inherit from the base template.

      • nano templates/index.html

      Add the following code to it:

      flask_app/templates/index.html

      {% extends 'base.html' %}
      
      {% block content %}
          <h1>{% block title %} Index {% endblock %}</h1>
          <h2>Welcome to FlaskApp!</h2>
      {% endblock %}
      

      Save and close the file.

      In the code above, you extend the base template and override the content block. You then set a page title and display it in an H1 header using the title block, and display a greeting in an H2 header.

      With the development server running, refresh the index page on your browser.

      You’ll see that the application displays no more errors and the index page is displayed as expected.

      You’ve now used debug mode and seen how to handle error messages. Next, you’ll abort a request to respond with an error message of your choice, and see how to respond with custom error pages.

      Step 2 — Creating Custom Error Pages

      In this step, you’ll learn how to abort requests and respond with a 404 HTTP error message for when the user requests data that does not exist on the server. You will also learn how to create custom error pages for common HTTP errors, such as the 404 Not Found error, and the 500 Internal Server Error error.

      To demonstrate how to abort requests and respond with a custom 404 HTTP error page, you’ll create a page that displays a few messages. If the requested message does not exist, you’ll respond with a 404 error.

      First, open your app.py file to add a new route for the messages page:

      Add the following route at the end of the file:

      flask_app/app.py

      # ...
      
      @app.route('/messages/<int:idx>')
      def message(idx):
          messages = ['Message Zero', 'Message One', 'Message Two']
          return render_template('message.html', message=messages[idx])
      

      Save and close the file.

      In the route above, you have a URL variable idx. This is the index that will determine what message will be displayed. For example, if the URL is /messages/0, the first message (Message Zero) will be displayed. You use the int converter to accept only positive integers, because URL variables have string values by default.

      Inside the message() view function, you have a regular Python list called messages with three messages. (In a real-world scenario, these messages would come from a database, an API, or another external data source.) The function returns a call to the render_template() function with two arguments, message.html as the template file, and a message variable that will be passed to the template. This variable will have a list item from the messages list depending on the value of the idx variable in the URL.

      Next open a new message.html template file:

      • nano templates/message.html

      Add the following code to it:

      flask_app/templates/message.html

      {% extends 'base.html' %}
      
      {% block content %}
          <h1>{% block title %} Messages {% endblock %}</h1>
          <h2>{{ message }}</h2>
      {% endblock %}
      

      Save and close the file.

      In the code above, you extend the base template and override the content block. You add a title (Messages) in an H1 heading, and display the value of the message variable in an H2 heading.

      With the development server running, visit the following URLs on your browser:

      http://127.0.0.1:5000/messages/0
      http://127.0.0.1:5000/messages/1
      http://127.0.0.1:5000/messages/2
      http://127.0.0.1:5000/messages/3
      

      You’ll see that the H2 contains the text Message Zero, Message One, or Message Two respectively on each one of the first three URLs. However, on the fourth URL, the server will respond with an IndexError: list index out of range error message. In a production environment, the response would’ve been a 500 Internal Server Error, but the proper response here is a 404 Not Found to indicate that the server can’t find a message with an index of 3.

      You can respond with a 404 error using Flask’s abort() helper function. To do so, open the app.py file:

      Edit the first line to import the abort() function. Then edit the message() view function by adding a try ... except clause as shown in the highlighted parts below:

      flask_app/app.py

      from flask import Flask, render_template, abort
      
      # ...
      # ...
      
      
      @app.route('/messages/<int:idx>')
      def message(idx):
          messages = ['Message Zero', 'Message One', 'Message Two']
          try:
              return render_template('message.html', message=messages[idx])
          except IndexError:
              abort(404)
      

      Save and close the file.

      In the code above, you import the abort() function, which you use to abort the request and respond with an error. In the message() view function, you use a try ... except clause to wrap the function. You first try to return the messages template with the message that corresponds to the index in the URL. If the index has no corresponding message, the IndexError exception will be raised. You then use the except clause to catch that error, and you use abort(404) to abort the request and respond with a 404 Not Found HTTP error.

      With the development server running, use your browser to revisit the URL that responded with an IndexError earlier (or visit any URL with an index greater than 2):

      http://127.0.0.1:5000/messages/3
      

      You will see the following response:

      Not Found
      
      The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
      

      You now have a better error message that indicates that the server could not find the requested message.

      Next, you’ll make a template for the 404 error page and one for the 500 error page.

      First, you’ll register a function with the special @app.errorhandler() decorator as a handler for the 404 error. Open the app.py file for editing:

      nano app.py
      

      Edit the file by adding the highlighted part as follows:

      flask_app/app.py

      from flask import Flask, render_template, abort
      
      app = Flask(__name__)
      
      
      @app.errorhandler(404)
      def page_not_found(error):
          return render_template('404.html'), 404
      
      
      @app.route('/')
      def index():
          return render_template('index.html')
      
      
      @app.route('/messages/<int:idx>')
      def message(idx):
          messages = ['Message Zero', 'Message One', 'Message Two']
          try:
              return render_template('message.html', message=messages[idx])
          except IndexError:
              abort(404)
      

      Save and close the file.

      Here you use the @app.errorhandler() decorator to register the function page_not_found() as a custom error handler. The function takes the error as an argument, and it returns a call to the render_template() function with a template called 404.html. You will create this template later, and you can use another name if you want. You also return the integer 404 after the render_template() call. This tells Flask that the status code in the response should be 404. If you don’t add it, the default status code response will be 200, which means that the request has succeeded.

      Next, open a new 404.html template:

      Add the following code to it:

      flask_app/templates/404.html

      {% extends 'base.html' %}
      
      {% block content %}
              <h1>{% block title %} 404 Not Found. {% endblock %}</h1>
              <p>OOPS! Sammy couldn't find your page; looks like it doesn't exist.</p>
              <p>If you entered the URL manually, please check your spelling and try again.</p>
      {% endblock %}
      

      Save and close the file.

      Just like any other template, you extend the base template, you replace the content of the content and title blocks, and you add your own HTML code. Here you have an <h1> heading as the title, a <p> tag with a custom error message telling the user the page was not found, and a helpful message for users who might have entered the URL manually.

      You can use whatever HTML, CSS, and JavaScript you want in your error pages in the same way you would in other templates.

      With the development server running, use your browser to revisit the following URL:

      http://127.0.0.1:5000/messages/3
      

      You’ll see the page now has the navigation bar that’s in the base template and the custom error message.

      Similarly, you can add a custom error page for your 500 Internal Server Error errors. Open the app.py file:

      Add the following error handler below the 404 error handler:

      flask_app/app.py

      # ...
      
      @app.errorhandler(404)
      def page_not_found(error):
          return render_template('404.html'), 404
      
      
      @app.errorhandler(500)
      def internal_error(error):
          return render_template('500.html'), 500
      
      # ...
      

      Here you use the same pattern as you did for the 404 error handler. You use the app.errorhandler() decorator with a 500 argument to make a function called internal_error() into an error handler. You render a template called 500.html, and respond with a status code of 500.

      Then to demonstrate how the custom error will be presented, add a route that responds with a 500 HTTP error at the end of the file. This route will always give a 500 Internal Server Error regardless of whether the debugger is running or not:

      flask_app/app.py

      
      # ...
      @app.route('/500')
      def error500():
          abort(500)
      

      Here you make a route /500 and use the abort() function to respond with a 500 HTTP error.

      Save and close the file.

      Next, open the new 500.html template:

      Add the following code to it:

      flask_app/templates/500.html

      {% extends 'base.html' %}
      
      {% block content %}
              <h1>{% block title %} 500 Internal Server Error {% endblock %}</h1>
              <p>OOOOPS! Something went wrong on the server.</p>
              <p>Sammy is currently working on this issue. Please try again later.</p>
      {% endblock %}
      

      Save and close the file.

      Here, you do the same thing you did with the 404.html template. You extend the base template, and replace the content block with a title and two custom messages informing the user about the internal server error.

      With the development server running, visit the route that responds with a 500 error:

      http://127.0.0.1:5000/500
      

      Your custom page will appear instead of the generic error page.

      You now know how to use custom error pages for HTTP errors in your Flask application. Next, you’ll learn how to use logging to track events in your application. Tracking events helps you understand how your code behaves, which in turn helps with development and troubleshooting.

      Step 3 — Using Logging to Track Events in Your Application

      In this step, you will use logging to track events that happen when the server is running and the application is being used, which helps you see what is going on in your application code so you can troubleshoot errors easier.

      You have already seen logs whenever the development server is running, which typically look like this:

      127.0.0.1 - - [21/Sep/2021 14:36:45] "GET /messages/1 HTTP/1.1" 200 -
      127.0.0.1 - - [21/Sep/2021 14:36:52] "GET /messages/2 HTTP/1.1" 200 -
      127.0.0.1 - - [21/Sep/2021 14:36:54] "GET /messages/3 HTTP/1.1" 404 -
      

      In these logs, you can see the following information:

      • 127.0.0.1: The host the server was running on.
      • [21/Sep/2021 14:36:45]: The date and time of the request.
      • GET: The HTTP request method. In this case, GET is used to retrieve data.
      • /messages/2: The path the user requested.
      • HTTP/1.1: The HTTP version.
      • 200 or 404: The status code of the response.

      These logs help you diagnose problems that occur in your application. You can log more information when you want to know more details about certain requests using the logger app.logger Flask provides.

      With logging, you can use different functions to report information on different logging levels. Each level indicates an event happened with a certain degree of severity. The following functions can be used:

      • app.logger.debug(): For detailed information about the event.
      • app.logger.info(): Confirmation that things are working as expected.
      • app.logger.warning(): Indication that something unexpected happened (such as “disk space low”), but the application is working as expected.
      • app.logger.error(): An error occurred in some part of the application.
      • app.logger.critical(): A critical error; the entire application might stop working.

      To demonstrate how to use the Flask logger, open your app.py file for editing to log a few events:

      Edit the message() view function to look as follows:

      flask_app/app.py

      
      # ...
      
      @app.route('/messages/<int:idx>')
      def message(idx):
          app.logger.info('Building the messages list...')
          messages = ['Message Zero', 'Message One', 'Message Two']
          try:
              app.logger.debug('Get message with index: {}'.format(idx))
              return render_template('message.html', message=messages[idx])
          except IndexError:
              app.logger.error('Index {} is causing an IndexError'.format(idx))
              abort(404)
      
      # ...
      

      Save and close the file.

      Here, you logged a few events on different levels. You use app.logger.info() to log an event that’s working as expected (which is an INFO level). You use app.logger.debug() for detailed information (DEBUG level), mentioning that the application is now getting a message with a specific index. Then you use app.logger.error() to log the fact that an IndexError exception has been raised with the specific index that caused the issue (ERROR level, because an error occurred).

      Visit the following URL:

      http://127.0.0.1:5000/messages/1
      

      You’ll see the following information in the terminal where your server is running:

      Output

      [2021-09-21 15:17:02,625] INFO in app: Building the messages list... [2021-09-21 15:17:02,626] DEBUG in app: Get message with index: 1 127.0.0.1 - - [21/Sep/2021 15:17:02] "GET /messages/1 HTTP/1.1" 200 -

      Here you see the INFO message app.logger.info() logs, and the DEBUG message with the index number that you logged using app.logger.debug().

      Now visit a URL for a message that does not exist:

      http://127.0.0.1:5000/messages/3
      

      You’ll see the following information in the terminal:

      Output

      [2021-09-21 15:33:43,899] INFO in app: Building the messages list... [2021-09-21 15:33:43,899] DEBUG in app: Get message with index: 3 [2021-09-21 15:33:43,900] ERROR in app: Index 3 is causing an IndexError 127.0.0.1 - - [21/Sep/2021 15:33:43] "GET /messages/3 HTTP/1.1" 404 -

      As you can see, you have INFO and DEBUG logs that you’ve seen before, and a new ERROR log because a message with an index of 3 does not exist.

      Logging events, detailed information, and errors helps you identify where something went wrong and makes troubleshooting easier.

      You’ve learned in this step how to use the Flask logger. Check out How To Use Logging in Python 3 for a better understanding of logging. For an in-depth look at logging, see the Flask logging documentation and the Python documentation for logging.

      Conclusion

      You now know how to use debug mode in Flask, and how to troubleshoot and fix some common errors you may encounter when developing a Flask web application. You’ve also created custom error pages for common HTTP errors, and you’ve used the Flask logger to track events in your application to help you inspect and figure out how your application behaves.

      If you would like to read more about Flask, check out the Flask topic page.



      Source link

      How to Fix Syntax Errors in WordPress


      If you found this article because you’re staring at a WordPress error message where your website used to be, take a deep breath and put on your superhero cape (tights are optional).

      Yes, there’s a problem, but it’s possible to fix it.

      Your site hasn’t disappeared into the ether. It’s still there, behind that error message. The issue may be something as simple as a missing semicolon in a PHP file. WordPress syntax errors aren’t frequent, but they do occur and are relatively simple to correct.

      In this article, we’ll explain what a syntax error is, along with some common causes. Then we’ll walk you through the steps to take to locate and fix the error. Let’s get started!

      What Is a Syntax Error?

      A syntax error occurs when a command is not written correctly.

      A WordPress syntax error message.

      This may include the presence of a grammatical mistake, a misspelled word or missing symbol, or an incorrect punctuation mark in your site’s code. In WordPress, this is usually a PHP error.

      Skip the Stress

      Avoid troubleshooting when you sign up for DreamPress. Our friendly WordPress experts are available 24/7 to help solve website problems — big or small.

      Common Causes of Syntax Errors in WordPress

      A syntax error may occur when you’ve pasted code incorrectly. Maybe you missed a portion when you copied the code or perhaps there is an extra closing tag at the end of the script.

      This is a PHP open tag: <?php, and this is a closing tag: ?>.

      When you copy and paste a PHP code snippet, it often includes the open tag, causing a syntax error. Since you are probably pasting the snippet into existing code, you don’t need to include the open tag.

      You may also get a syntax error when you are editing your theme in the WordPress Customizer. If this happens, you’ll generally know what the problem is, or at least where in the file it’s occurring. If you aren’t sure, don’t worry. You can locate the error by making a few changes to the wp-config.php file.

      Another reason you might see this message is because of a plugin update or installation. The extension may not be compatible with your WordPress version, or there may be other issues at play. If you were updating or installing a plugin when the error happened, that’s most likely the source of the problem.

      Why Fixing the WordPress Syntax Error Matters

      A syntax error is an indication that something isn’t right within your site’s code. This issue can break your website, leaving you with a blank page or error message.

      If your website is down or inaccessible, it will obviously hamper the User Experience (UX). Besides hurting your traffic and conversion rates, having a blank page where your site should be can also hurt your Search Engine Optimization (SEO) rankings.

      WordPress syntax error messages can be concerning, especially if you aren’t familiar with website code. Fortunately, as you’ll see, most syntax errors have a simple solution.

      How to Fix a Syntax Error in WordPress via SFTP

      When a syntax error occurs, you can fix it by either removing or correcting the code containing the error. Either way, you’ll need access to the file where the problem is occurring. If you’re locked out of your WordPress admin dashboard, you can access this by using a File Transfer Protocol (FTP) client.

      If you’re a DreamHost customer, this process is especially easy. There’s no need to download a third-party application. You can access your website files using our dedicated WebFTP tool.

      DreamHost’s WebFTP login screen.

      If you aren’t a DreamHost customer or prefer to use an FTP client, FileZilla is a good option. Note that you’ll always want to connect using the more secure Secure File Transfer Protocol (SFTP) rather than FTP. This will ensure the transferred data is encrypted.

      You will need some information to connect to your website via SFTP:

      • Server/Hostname
      • Username
      • Password
      • Port

      You can find this information by logging into your web hosting account. DreamHost users can navigate to Manage Account. If you’re using another hosting provider, they may call this area something different — if you need help, contact your host or visit their knowledge base.

      From the account management area, look for FTP Users (or FTP Accounts, depending on your web host) and select Manage Users to view your Host, Username, and Port settings. If you don’t know your FTP password, you can reset it with the link provided.

      DreamHost FTP user information.

      Next, open your FTP client and enter your login credentials. Once logged in, under your WordPress site’s directory, you will see the wp-adminwp-content, and wp-includes folders, and a list of other files.

      A WordPress site directory via SFTP.

      If your screen looks similar to the above example, you’re in the right place! Now, it’s time to enable debugging to get more information about the syntax error.

      Enable Debugging to View the Syntax Error Location

      If you were working on your website when the error occurred, you should have a good idea of where to look for the issue. However, if you’re unsure, there’s no need to guess. Debugging will show you the exact location of the error.

      To enable debugging, you can add the following snippet of code to your wp-config.php file:

      define( 'WP_DEBUG', true );

      Be sure to put the code before /* That’s all, stop editing! Happy blogging. */ toward the bottom of the file.

      WordPress debugging code added to the ‘wp-config.php’ file.

      Once you save the file and refresh your website in your browser, you should see a text string indicating the location of the error, including the file, name, and line number.

      A WordPress syntax error message.

      Be sure to disable debugging once you’ve fixed the syntax errors, as leaving this feature on isn’t recommended for live websites.

      You’ve now located the syntax error. After noting the information, it’s time to get to work fixing it. You can use the directions below to address the error according to its location.

      Fix a Syntax Error Caused By a Plugin Update

      If you were installing, updating, or editing a plugin file when the syntax error occurred, the simplest and fastest solution is to disable the plugin. That’s what we’ll do first.

      Access your website via SFTP. Once you’re connected, go to the wp-content/plugins directory, and locate the plugin folder with the error.

      While there, you can either disable the plugin or correct the file that contains the error — if you know what’s causing the issue. If not, you can disable the plugin by renaming its folder in the plugins directory.

      If you go to your website’s URL and refresh the browser, your site should appear normal. However, if you want to continue using the plugin, you’ll need to resolve the error rather than simply disabling it.

      To correct the plugin error, locate the file and line number from the error message. Identify any missing or incorrect code on that line. If you’re unsure what’s causing the error, you can paste the snippet into a code editor to help you identify it.

      You can always disable the plugin as a short-term fix. Then, you can reactivate it later, once the error is corrected. This may be the best approach, especially if the plugin isn’t essential to your website’s operation.

      Fix Syntax Error Caused By Editing a Theme File Improperly

      To fix an error that occurred while editing your theme, access your website via SFTP, and navigate to the wp-content/themes folder. Open the appropriate theme folder and locate the file with the error — usually the functions.php file.

      Edit the file and correct the error. Again, the syntax error code should display the line number. If the problem occurred when you pasted a code snippet into the file, delete your edits to restore the file to its stable version.

      If you don’t see what’s causing the problem, you can use a code editor to help identify the error. Once you correct the problem, open a browser window, and navigate to your URL to verify that your site is up and running again.

      Use a Code Editor to Identify Syntax Errors

      There are several free code editors available online, like Sublime Text and Atom. You can use any of these tools to help diagnose and fix syntax errors.

      In the illustration below, the functions.php file is missing a semicolon on the last line.

      Syntax errors shown in a code editor.

      The editor indicates the syntax error with a yellow bar beside the line number (610). Once we add the semicolon, the error resolves, and the yellow flag disappears. You can practice writing or editing code in an editor before making changes to your website’s files.

      How to Avoid Syntax Errors in the Future

      Using proper syntax can help you avoid errors in the future. PHP is a simple, flexible language. You can invest a little time to learn the basics. Then, when you’re pasting code or making edits to your site’s files, you’ll know how to correct errors as you work.

      As another option, you can keep a code editor handy to check syntax before pasting code into your website. This is a smart practice for ensuring that a code snippet is correct before adding it to files on a live site.

      Another way to prevent issues is to enable debugging when making changes to your site, in order to flag errors before going live. This is the time to make sure everything is compatible with your WordPress core files and works as it should.

      Finally, we suggest deleting any unused plugins and themes. Not only can this help prevent syntax errors, but it is also a good security measure, so it’s a win-win.

      Take Your WordPress Site to the Next Level

      Whether you need help navigating the WordPress dashboard, decoding an error log, or fixing a faulty plugin, we can help! Subscribe to our monthly digest so you never miss an article.

      Ready to Fix That Syntax Error?

      Almost 40% of all websites are built on WordPress, making it the most popular Content Management System (CMS) in the world. It’s a stable and secure platform, but even so, errors can still happen.

      In this article, we explained what syntax errors are and their most common causes. Then we provided a step-by-step guide for fixing syntax errors in your WordPress installation. These are usually simple to resolve, but it’s best to take measures to prevent the problems from appearing in the first place, such as using a code editor to check code before adding it to your site.

      Properly maintaining your website is one of the best ways to avoid issues and keep it running smoothly. DreamPress hosting (with free WordPress migration) is specifically designed for the WordPress environment. Plus, if you ever do encounter a problem, we’ve got you covered with automatic daily backups and a support team of WordPress experts!



      Source link