Featured image of post Go Database Error Details: Effective Diagnosis and Resolution

Go Database Error Details: Effective Diagnosis and Resolution

When working with Databases in Go, it can be useful to get detailed error messages. This Article explains how you can get this information.

Home / Posts / Go Database Error Details: Effective Diagnosis and Resolution

Are you working with Go to access a database but struggling to diagnose errors due to lack of details in the error messages? If so, you’re not alone. In this post, I’ll walk you through some techniques to extract more detailed error information so that you can identify and resolve issues in your code.

Default error messages in Go

Consider a basic Go code that uses db.Exec to execute an INSERT query.

1
2
3
4
_, err := db.Exec(query, params...)
if err != nil {
    log.Print(err)
}

However, upon execution, the code encounters an error and displays the following message:

1
2
2023/03/10 09:40:26 pq: insert or update on table "table" violates foreign key constraint "table_constraint"
exit status 1

This error message indicates that a constraint is being violated and the INSERT operation cannot be executed. However, if you’re working with large amounts of data, this error message may not provide enough information to pinpoint exactly which data is causing the issue.

Custom error type implementation by Driver

So, you’re now looking to obtain more detailed information about the error. But how can you achieve this? Well, in Go, each database driver is unique and implements its own custom error. For instance, let’s consider two examples: MySQL and PostgreSQL.

PostgreSQL

type Error implementation for PostgreSQL

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
type Error struct {
	Severity         string
	Code             ErrorCode
	Message          string
	Detail           string
	Hint             string
	Position         string
	InternalPosition string
	InternalQuery    string
	Where            string
	Schema           string
	Table            string
	Column           string
	DataTypeName     string
	Constraint       string
	File             string
	Line             string
	Routine          string
}

The error implementation of PostgreSQL provides an extensive array of fields that offer a wealth of information regarding the error you’re currently encountering.

MySQL

type MySQLError implementation for MySQL

1
2
3
4
5
type MySQLError struct {
	Number   uint16
	SQLState [5]byte
	Message  string
}

While the MySQL error implementation is different from PostgreSQL’s, it still offers supplementary information regarding errors.

How to use the custom error types to get more details about the error?

Let’s dive into working with custom error types, which is quite straightforward. Essentially, all you’re doing is performing a type assertion with the custom error type.

1
2
3
4
5
6
_, err := db.Exec(query, params...)
if err != nil {
    if e, ok := err.(*pq.Error); ok {
        log.Print(e.Detail)
    }
}

To quickly recap, when an error occurs, we use a type assertion to match it with the corresponding custom error type of the database driver being used, such as PostgreSQL. This allows us to access all the fields provided by the custom error type, which can be immensely helpful in debugging and resolving the error.

In my case, it showed me the exact issue that was causing the constraint. With this information it was easy to find the wrong data and correct it.

1
DETAIL:  Key (id)=(abc) is not present in table "table_2".
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy