Home > Mobile >  Service fails randomly: "runtime error: invalid memory address or nil pointer dereference"
Service fails randomly: "runtime error: invalid memory address or nil pointer dereference"

Time:02-15

I am working on a Restful API server and I had to migrate from MongoDB to MySQL. The ORM the team picked up is upper/db. My issue is that my service fails some times, some times it doesn't.

The error itself: runtime error: invalid memory address or nil pointer dereference

This is the service function that gives me error some times:

func (service *UserService) UpdateUser(req UpdateUserRequest) (response UpdateUserResponse, err error) {
    var user models.User
    defer service.db.Close()
    collection := service.db.Collection("users")

    result := collection.Find(req.ID)

    err = result.One(&user) // this is line 104
    if err != nil {
        return
    }

    count, err := result.Count()
    if err != nil {
        return
    }
    if count == 0 {
        err = errors.New("couldn't find user")
        return
    }

    if req.FirstName != "" && req.FirstName != user.FirstName {
        user.FirstName = req.FirstName
    }
    if req.LastName != "" && req.LastName != user.LastName {
        user.LastName = req.LastName
    }
    if req.UserType != "" && req.UserType != user.UserType {
        user.UserType = req.UserType
    }
    if req.Status != "" && req.Status != user.Status {
        user.Status = req.Status
    }

    user.UpdatedAt = time.Now()

    if err = result.Update(user); err != nil {
        return
    }

    user.Password = ""

    response.User = user
    return
}

I am following the official documentation. Something strange is the first time (after the server starts) it updates the user successfully, the next don't.

Edit: Error dump added:

runtime error: invalid memory address or nil pointer dereference
C:/Program Files/Go/src/runtime/panic.go:221 (0xfe993c)
        panicmem: panic(memoryError)
C:/Program Files/Go/src/runtime/signal_windows.go:254 (0xfe990c)
        sigpanic: panicmem()
C:/Program Files/Go/src/database/sql/sql.go:1260 (0x14452d3)
        (*DB).conn: db.mu.Lock()
C:/Program Files/Go/src/database/sql/sql.go:1695 (0x144831c)
        (*DB).query: dc, err := db.conn(ctx, strategy)
C:/Program Files/Go/src/database/sql/sql.go:1674 (0x144807e)
        (*DB).QueryContext: rows, err = db.query(ctx, query, args, cachedOrNewConn)
C:/Users/user/go/pkg/mod/github.com/upper/db/[email protected]/internal/sqladapter/compat/query_go18.go:39 (0x1486730)
        QueryContext: return p.QueryContext(ctx, query, args...)
C:/Users/user/go/pkg/mod/github.com/upper/db/[email protected]/internal/sqladapter/session.go:823 (0x14866eb)
        (*session).StatementQuery: rows, err = compat.QueryContext(sess.sqlDB, ctx, query, args)
C:/Users/user/go/pkg/mod/github.com/upper/db/[email protected]/internal/sqlbuilder/select.go:480 (0x147304f)
        (*selector).IteratorContext: rows, err := sess.StatementQuery(ctx, sq.statement(), sq.arguments()...)
C:/Users/user/go/pkg/mod/github.com/upper/db/[email protected]/internal/sqlbuilder/select.go:470 (0x1472d9a)
        (*selector).Iterator: return sel.IteratorContext(sel.SQL().sess.Context())
C:/Users/user/go/pkg/mod/github.com/upper/db/[email protected]/internal/sqlbuilder/paginate.go:176 (0x146d932)
        (*paginator).Iterator: return pq.sel.Iterator()
C:/Users/user/go/pkg/mod/github.com/upper/db/[email protected]/internal/sqladapter/result.go:243 (0x14809b5)
        (*Result).One: err = query.Iterator().One(dst)
C:/Users/user/go/src/github.com/myrepo/service/services/user_service.go:104 (0x15135be)
        (*UserService).UpdateUser: err = result.One(&user)
C:/Users/user/go/src/github.com/myrepo/service/handlers/users_handler.go:39 (0x1518e3c)
        handleUpdateUser.func1: user, err := service.UpdateUser(req)
C:/Users/user/go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:168 (0x1515ff6)
        (*Context).Next: c.handlers[c.index](c)
C:/Users/user/go/pkg/mod/github.com/tpkeeper/[email protected]/gindump.go:98 (0x15153b4)
        DumpWithOptions.func1: ctx.Next()
C:/Users/user/go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:168 (0x14311a6)
        (*Context).Next: c.handlers[c.index](c)
C:/Users/user/go/pkg/mod/github.com/gin-gonic/[email protected]/logger.go:241 (0x1431189)
        LoggerWithConfig.func1: c.Next()
C:/Users/user/go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:168 (0x1431f41)
        (*Context).Next: c.handlers[c.index](c)
C:/Users/user/go/pkg/mod/github.com/gin-gonic/[email protected]/recovery.go:99 (0x1431f2c)
        CustomRecoveryWithWriter.func1: c.Next()
C:/Users/user/go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:168 (0x1430730)
        (*Context).Next: c.handlers[c.index](c)
C:/Users/user/go/pkg/mod/github.com/gin-gonic/[email protected]/gin.go:555 (0x1430398)
        (*Engine).handleHTTPRequest: c.Next()
C:/Users/user/go/pkg/mod/github.com/gin-gonic/[email protected]/gin.go:511 (0x142fed1)
        (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
C:/Program Files/Go/src/net/http/server.go:2879 (0x120959a)
        serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
C:/Program Files/Go/src/net/http/server.go:1930 (0x1204c47)
        (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
C:/Program Files/Go/src/runtime/asm_amd64.s:1581 (0x1004640)
        goexit: BYTE    $0x90   // NOP

Edit 2: Added database connection

func Open(settings db.ConnectionURL) (db.Session, error) {
    db, err := mysql.Open(settings)
    if err != nil {
        return nil, err
    }

    if db.Ping() != nil {
        return nil, errors.New("error al conectar la base de datos")
    }

    return db, nil
}

What am I doing wrong?

CodePudding user response:

The function UpdateUser closes the database on return. That's big problem! The subsequent calls to UpdateUser panic because the function calls methods on the closed database.

Delete this line of code to fix the issue.

defer service.db.Close()
  • Related