{"record":{"id":"d629b8c73191ce5c","repo":"hibiken/asynq","slug":"internal","errorCode":"Internal","errorMessage":"cast error: Lua script returned unexpected value: %v","messagePattern":"cast error: Lua script returned unexpected value: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/rdb/inspect.go","lineNumber":705,"sourceCode":"\tcase base.TaskStateActive:\n\t\tkey = base.ActiveKey(qname)\n\tcase base.TaskStatePending:\n\t\tkey = base.PendingKey(qname)\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unsupported task state: %v\", state))\n\t}\n\t// Note: Because we use LPUSH to redis list, we need to calculate the\n\t// correct range and reverse the list to get the tasks with pagination.\n\tstop := -pgn.start() - 1\n\tstart := -pgn.stop() - 1\n\tres, err := listMessagesCmd.Run(context.Background(), r.client,\n\t\t[]string{key}, start, stop, base.TaskKeyPrefix(qname)).Result()\n\tif err != nil {\n\t\treturn nil, errors.E(errors.Unknown, err)\n\t}\n\tdata, err := cast.ToStringSliceE(res)\n\tif err != nil {\n\t\treturn nil, errors.E(errors.Internal, fmt.Errorf(\"cast error: Lua script returned unexpected value: %v\", res))\n\t}\n\tvar infos []*base.TaskInfo\n\tfor i := 0; i < len(data); i += 2 {\n\t\tm, err := base.DecodeMessage([]byte(data[i]))\n\t\tif err != nil {\n\t\t\tcontinue // bad data, ignore and continue\n\t\t}\n\t\tvar res []byte\n\t\tif len(data[i+1]) > 0 {\n\t\t\tres = []byte(data[i+1])\n\t\t}\n\t\tvar nextProcessAt time.Time\n\t\tif state == base.TaskStatePending {\n\t\t\tnextProcessAt = r.clock.Now()\n\t\t}\n\t\tinfos = append(infos, &base.TaskInfo{\n\t\t\tMessage:       m,\n\t\t\tState:         state,","sourceCodeStart":687,"sourceCodeEnd":723,"githubUrl":"https://github.com/hibiken/asynq/blob/d135f1439bee74e989b7f9b41ecd542cc87f024a/internal/rdb/inspect.go#L687-L723","documentation":"listMessages runs a Lua script over a Redis list and expects the result to be convertible to []string of message payloads. When cast.ToStringSliceE fails, the raw Lua return value has an unexpected shape, and the library wraps it in an errors.E(errors.Internal, ...) with this message. It indicates a mismatch between what the Lua script returned and what the Go code expects.","triggerScenarios":"Calling ListPending or ListActive when the Redis Lua script returns a non-slice value (e.g. an error reply, a single scalar, or a nested table) — typically caused by a Redis version whose scripting behavior differs, or corrupted/reshaped keys so the script takes an unexpected branch.","commonSituations":"Running against an incompatible Redis server (e.g. a proxy or cluster middleware like Twemproxy/Codis that mangles Lua multi-bulk replies); a Redis version upgrade changing reply formatting; manually altered or corrupted task-list keys.","solutions":["Check the Redis endpoint: point the client at a plain Redis server that fully supports Lua scripting (not a proxy that strips multi-bulk replies).","Log/capture the `res` value shown in the message to see the actual shape returned and compare with what the Lua script should return.","Verify Redis server version compatibility with the library and flush/repair corrupted queue keys (e.g. inspect keys with the task-key prefix manually)."],"exampleFix":"// before\nrdb := redis.NewClient(&redis.Options{Addr: proxyAddr}) // proxy mangles Lua replies\ninfos, err := inspector.ListPending(\"default\")\n// after\nrdb := redis.NewClient(&redis.Options{Addr: \"127.0.0.1:6379\"})\nif err := rdb.Eval(ctx, \"return 1\", nil).Err(); err != nil {\n    log.Fatal(\"redis does not support scripting: \", err)\n}\ninfos, err := inspector.ListPending(\"default\")","handlingStrategy":"try-catch","validationCode":"if err := rdb.Ping(ctx).Err(); err != nil {\n    return err\n}\n// probe scripting support before listing\nif err := rdb.Eval(ctx, \"return 1\", nil).Err(); err != nil {\n    return fmt.Errorf(\"redis scripting unavailable: %w\", err)\n}","typeGuard":"if _, ok := res.([]interface{}); !ok {\n    return fmt.Errorf(\"unexpected Lua reply type %T\", res)\n}","tryCatchPattern":"infos, err := inspector.ListPending(qname)\nif err != nil {\n    var e *errors.Error\n    if errors.As(err, &e) && e.Code == errors.Internal && strings.Contains(err.Error(), \"cast error\") {\n        log.Printf(\"bad Lua reply for queue %s: %v\", qname, err)\n        return nil // degrade gracefully\n    }\n    return err\n}","preventionTips":["Avoid Redis proxies (twemproxy, some cluster shims) that break Lua multi-bulk replies.","Pin a Redis server version compatible with the library.","Monitor queue keys for corruption and test List* endpoints after Redis upgrades."],"tags":["redis","lua-script","type-cast","internal-error"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"d135f1439bee74e989b7f9b41ecd542cc87f024a","analyzedAt":"2026-09-07T19:02:34.660Z","contentChangedAt":"2026-09-07T19:02:34.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}