Error whilst making RPC call: SyntaxError: Unexpected end of JSON input

accountUpdateId() → Throws: Error whilst making RPC call: SyntaxError: Unexpected end of JSON input

:test_tube: TL;TR

Running an RPC call from the Nakama Console results in:
Error whilst making RPC call: SyntaxError: Unexpected end of JSON input

:desktop_computer: Current setup:

  1. Versions: Nakama 3.22.0 running in a Docker container (macOS)
  2. Server Framework Runtime language: TS/JS

:man_technologist: rpcUpdateLastOnline()

In the minimal code example of index.js below, you find the rpcUpdateLastOnline() function.
This function behavior should be: setting the current users metadata field: lastOnline with the current date stamp when he/she goes offline.
The function is a modification of the example mentioned here: heroiclabs.com/reference/#accountUpdateId

"use strict";
function InitModule(ctx, logger, nk, initializer) {
    initializer.registerRpc('healthcheck', rpcHealthCheck);
    initializer.registerRpc('updateLastOnline', rpcUpdateLastOnline);
    logger.info('Javascript InitModule loaded');
}
function rpcHealthCheck(ctx, logger, nk, payload) {
    logger.info('HealthCheck RPC called');
    return JSON.stringify({ success: true });
}
// RPC function to update last_online metadata for the current user
function rpcUpdateLastOnline(ctx, logger, nk, payload) {
    if (!ctx.userId) {
        throw Error('No user ID in context');
    }
    if (payload) {
        throw Error('no input allowed');
    }
    var userId = ctx.userId;
    var username = null;
    var now = new Date().toISOString();
    var metadata = { lastOnline: now };
    var displayName = null;
    var timezone = null;
    var location = null;
    var langTag = null;
    var avatarUrl = null;
    try {
        nk.accountUpdateId(userId, username, displayName, timezone, location, langTag, avatarUrl, metadata);
    }
    catch (error) {
        logger.error('updateLastOnline error: %q', error);
        throw error;
    }
};

The Issue:

Running the RPC call from the Nakama Console results in:
Error whilst making RPC call: SyntaxError: Unexpected end of JSON input

:cross_mark: When I chance the code to only update the displayName I also get the same error as mentioned above:

var userId = ctx.userId;
    var username = null;
    var metadata = null;
    var displayName = "MyName";
    var timezone = null;
    var location = null;
    var langTag = null;
    var avatarUrl = null;
    try {
        nk.accountUpdateId(userId, username, displayName, timezone, location, langTag, avatarUrl, metadata);

:+1: BUT when all arguments (other than userId) are null like below…

var userId = ctx.userId;
    var username = null;
    var metadata = null;
    var displayName = null;
    var timezone = null;
    var location = null;
    var langTag = null;
    var avatarUrl = null;
    try {
        nk.accountUpdateId(userId, username, displayName, timezone, location, langTag, avatarUrl, metadata);

I get an expected reponse:

"rpc error: code = Internal desc = GoError: error trying to update user: 
No fields to update. at github.com/heroiclabs/nakama/v3/server
.(*runtimeJavascriptNakamaModule).mappings.
(*runtimeJavascriptNakamaModule).accountUpdateId.func40 (native)"

:confused: ???

Somehow - I think - the generated JSON string does not get constructed/parsed the right way. And I am scratching my head for hours to tackle this.

What am I missing?

:up_arrow: Follow up

Just tried this with another code example from the docs:

function rpcUpdateWallet(ctx, logger, nk, payload) {
        var user_id = ctx.userId
        var changeset = {
                coins: 10, // Add 10 coins to the user's wallet.
        };
        var metadata = {
                gameResult: 'won'
        };
        var result;
        try {
                result = nk.walletUpdate(user_id, changeset, metadata, true);
        }
        catch (error) {
                logger.error('updateWallet error: %q', error);
                throw error;
        }
}

:warning: And it also gives me:

Error whilst making RPC call: SyntaxError: Unexpected end of JSON input

Do I need to wrap/unwrap the JSON strings? :thinking:

:magnifying_glass_tilted_left: SOLVED!

Nakama expects every RPC function to return a string.
If your function doesn’t explicitly return anything, Nakama will try to parse undefined as JSON, resulting in:

"SyntaxError: Unexpected end of JSON input"

:white_check_mark: Solution: Add a return statement

Update both functions to return a JSON-encoded string.

:white_check_mark: rpcUpdateLastOnline:

function rpcUpdateLastOnline(ctx, logger, nk, payload) {
    ...
    nk.accountUpdateId(...);
    return JSON.stringify({ success: true });
}

:white_check_mark: rpcUpdateWallet:

function rpcUpdateWallet(ctx, logger, nk, payload) {
    ...
    nk.walletUpdate(...);
    return JSON.stringify({ success: true });
}

:brain: TL;DR

  • The error is not caused by bad input, but by no return value.
  • Always return a string from Nakama RPC functions — even just: return JSON.stringify({}).
  • :laughing: I’m stupid