Redigo: `NOSCRIPT No matching script. Please use EVAL.`

Created on 20 Jul 2018  路  17Comments  路  Source: gomodule/redigo

while doing a script.Do(...) I recieve the following error: NOSCRIPT No matching script. Please use EVAL.

But when i look at the code, it's not supposed to happend

func (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error) {
    v, err := c.Do("EVALSHA", s.args(s.hash, keysAndArgs)...)
    if e, ok := err.(Error); ok && strings.HasPrefix(string(e), "NOSCRIPT ") {
        v, err = c.Do("EVAL", s.args(s.src, keysAndArgs)...)
    }
    return v, err
}

Any idea how to fix it?

Most helpful comment

I think that's the point.
one package is using "github.com/gomodule/redigo/redis" and another one "github.com/garyburd/redigo/redis".
I'll make the Println asap

All 17 comments

Hello @jney

Have you created the script? What are you doing before script.Do(...)?

I didn't create the script. I think (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error) is supposed to do it for me, or?

a little more information, it works locally, and it is failing on aws elasticache

and i actually just use go-redis-queue

I created once through redis-ci:

$ redis-cli -h redis.staging.local EVAL "$(cat myscript)" 3 1 1 1

I guess it use EVALSHA now, so it seems to work (at least no error raised for now).
It is a really short term fix, I still have to figure out where the problem comes from, because it will probably happen in every of my other environment.

The only explanation for the reported behavior is that EVAL returns the error NOSCRIPT No matching script. Please use EVAL. It seems unlikely that the Redis server will return this error from EVAL.

@jney Please post a simple program showing how to reproduce the problem.

@garyburd as i told in a previous comment, this is the script included in this package which doesn't EVAL the script properly. but I don't think it is about go-redis-queue or redigo as it works as it should locally in a docker, the error only happen on aws' elasticache

Print the error with %q format to verify that the error is exactly NOSCRIPT No matching script. Please use EVAL as reported. Perhaps there's a leading space or other byte that causes strings.HasPrefix(string(e), "NOSCRIPT ") to return false.

with logger.Errorf("lock script failed: %q", err) : "lock script failed: \"NOSCRIPT No matching script. Please use EVAL.\""

Closing per my earlier comment.

@garyburd i don't understand your point..
Isn't *redis Script.Do supposed to create the script?

Do() does create the script. If EVALSHA command returns an error starting with the text "NOSCRIPT ", then Do() falls back to calling the EVAL command. The EVAL command creates the script.

The only explanation for what you reported is that EVAL returns the error NOSCRIPT No matching script. Please use EVAL, This seems unlikely. I suspect something else is going on, but it's difficult to know because you have not posted a simple program showing how to reproduce the problem.

var lockScript = redis.NewScript(1, `
local key = KEYS[1]
local ttl = redis.call("ttl", key)
if ttl > 0 then return ttl end
redis.call("set", key, "", ARGV[1])
return 0`)

func ttl(c redis.Conn, sessionID string) int {
    ttl, err := redis.Int(lockScript.Do(c, keyPrefix+sessionID, lockDuration))
    if err != nil {
        logger.Errorf("lock script failed: %q", err)
        return lockDuration
    }
    return ttl
}

I put log everywhere, and here my (ununderstandable) conclusion.
I kept here the most relevant log, for my demonstration:

func (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error) {
    v, err := c.Do("EVALSHA", s.args(s.hash, keysAndArgs)...)
    if err != nil {
        _, ok := err.(Error)
        fmt.Printf("script error: %v\t%t\n", err, ok)
    }
    if e, ok := err.(Error); ok && strings.HasPrefix(string(e), "NOSCRIPT ") {
        v, err = c.Do("EVAL", s.args(s.src, keysAndArgs)...)
    }
    return v, err
}

fmt.Printf("script error: %v\t%t\n", err, ok) gave me the following log:

script error: NOSCRIPT No matching script. Please use EVAL. false

Notice false at the end. I don't understand why but in this environment, it can not cast the error, so EVAL is never executed

by the way adding the log line:

fmt.Printf("type/cast: %T\t%t\n", err, ok)

give me:

type/cast: redis.Error false

Add the following log line and report the results. Perhaps you have two redis packages.

   fmt.Println(reflect.TypeOf(err).PkgPath(), reflect.TypeOf(Error(""))

I think that's the point.
one package is using "github.com/gomodule/redigo/redis" and another one "github.com/garyburd/redigo/redis".
I'll make the Println asap

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lukasmalkmus picture lukasmalkmus  路  18Comments

Serhioromano picture Serhioromano  路  7Comments

elimisteve picture elimisteve  路  7Comments

V2Vz picture V2Vz  路  4Comments

samwhitecoull picture samwhitecoull  路  3Comments