Strange error with clienr.rpc() about json parse error that works and then fails with same payload

I have a strange thing happening, using latest nakama server and nakama-js bindings.

I’m sending some rpc calls with client.rpc(), and it works for one rpc call, for the other I get a json parse error (SyntaxError: “JSON.parse: unexpected non-whitespace character after JSON data at line 1 column 6 of the JSON data”)

Even though the object is valid json and works elsewhere, I even tried putting it in the other rpc call that works and it was fine.
I even tried putting an empty object in both rpc calls, I get the same strange behaviour with the first working and the other giving a json parse error.

Except for the different rpc method string, everything else is identical.

What could be the issue?

More info, here is the exact error at the client side.

Error sending rpc: SyntaxError: “JSON.parse: unexpected non-whitespace character after JSON data at line 1 column 6 of the JSON data”
__node_modules heroiclabs/nakama-js/dist/nakama-js.umd.js:4660

This looks like you are sending malformed data as the RPC response from the server to the client.

Can you print the exact output you are sending from the server to the client? What does your server code look like?

This is the exact code for the non-working function. Note that it’s mostly copied from the docs.

local function create_match(context, payload)
    local modulename = 'match_handler'
    local setupstate = {initialstate = payload}
    if payload.label then
        setupstate.label = payload.label
    end
    local matchid = nk.match_create(modulename, setupstate)

    -- Send notification of some kind
    return matchid
end
nk.register_rpc(create_match, 'create_match_rpc')

Here’s the server function that works for reference (also from docs).

local function find_match(search_label)
    search_label = search_label or default_search_label

    local matches = nk.match_list(search_limit, isAuthoritative, search_label, min_size, max_size)
    if (#matches > 0) then
        table.sort(
            matches,
            function(a, b)
                return a.size > b.size
            end
        )
        return matches[1].match_id
    else
        return nil
    end
    -- local modulename = 'match_handler'
    -- local initialstate = {}
    -- local match_id = nk.match_create(modulename, initialstate)
    -- return match_id
end

And the rpc call:

local function quick_find_match(context, payload)
    local match_id = find_match(payload and payload.search_label)

    return match_id
end

nk.register_rpc(quick_find_match, 'quick_find_match_rpc')

I think the reason why the find_match function works is that it is returning nil - where as create_match always returns a string value.

Try wrapping the output of the RPCs with an object like this:

 return nk.json_encode({["match_id"] = matchid})

Thank you it worked!

For future reference, below are the working functions in one blob.

local nk = require('nakama')

local function create_match(context, payload)
    local modulename = 'match_handler'
    local setupstate = {initialstate = nk.json_decode(payload)}
    if setupstate.initialstate.label then
        setupstate.label = setupstate.initialstate.label 
    end
    local matchid = nk.match_create(modulename, setupstate)

    -- Send notification of some kind
    return nk.json_encode({['match_id'] = matchid})
end
nk.register_rpc(create_match, 'create_match_rpc')

local min_size = 2
local max_size = 2
local search_limit = 100
local isAuthoritative = true
local default_search_label = '+label.visibility:public'
local function find_match(search_label)
    search_label = search_label or default_search_label

    local matches = nk.match_list(search_limit, isAuthoritative, search_label, min_size, max_size)
    if (#matches > 0) then
        table.sort(
            matches,
            function(a, b)
                return a.size > b.size
            end
        )
        return matches[1].match_id
    else
        return nil
    end
end

local function quick_find_match(context, payload)
    local match_id = find_match(payload and nk.json_decode(payload).search_label)

    return nk.json_encode({['match_id'] = matchid})
end

nk.register_rpc(quick_find_match, 'quick_find_match_rpc')
2 Likes