Bug? StorageWrite not working as expected

Two code examples. Both should work, but only B does.

I try to “create or update” an object in storage engine:

  let version = undefined; // ...
  const saveItem = {
    collection: COLLECTION_XS,
    key: req.id,
    userId: ctx.userId,
    value: x,
    version: version,
    permissionRead: 1,
    permissionWrite: 0
  } as nkruntime.StorageWriteRequest;
  const ack = nk.storageWrite([saveItem]);
  // TypeError: expects 'version' value to be a string at github.com/heroiclabs/nakama/v3/server.(*runtimeJavascriptNakamaModule).storageWrite.func1 (native)

  let version = undefined;
  const saveItem = {
    collection: COLLECTION_XS,
    key: req.id,
    userId: ctx.userId,
    value: x,
    // version: version, // omited
    permissionRead: 1,
    permissionWrite: 0
  } as nkruntime.StorageWriteRequest;
  const ack = nk.storageWrite([saveItem]);
  // Works

So in order to actually create an object, i have to branch my code so in the create aspect i do not supply a version property? Your API defines nkruntime.StorageWriteRequest->version to be undefined, but then in the execution it fails. Thats a clear contradiction…

  1. Versions: I was on Nakama 3.14, upgraded to latest (went through a lot of pain upgrading cockroach; the previous cockroach version is completly uncompatible with newer nakama builds, you get very strange errors there) but the same behavior on the new version.
  2. Server Framework Runtime language (If relevant) TS

I am having a workaround thanks to lodash’s omitBy function, which removes all undefined values. I thought i leave this here for others.

  const saveItem = _omitBy({ ... }, _isUndefined) as unknown as nkruntime.StorageWriteRequest;
  const ack = nk.storageWrite([saveItem]);

As said, this is an error in nakama-common type declaration and needs a fix. I don’t see where in the code exactly this is done so i am not sure where to even start debugging (i’m no Go dev)

If you pass in a version during write, you are telling the server to do a “conditional write” - see this:

i understand that. It’s a problem with your type definitions!

nkruntime.StorageWriteRequest allows “version” to be undefined (which is correct). But if set and it’s value is undefined, the code fails at runtime with said error:
TypeError: expects 'version' value to be a string at github.com/heroiclabs/nakama/v3/server.(*runtimeJavascriptNakamaModule).storageWrite.func1 (native)

@mofirouz if you tell me where the code of nkruntime.StorageWriteRequest is, i may be able to open a pull request to fix it…

@dela I’m not sure I understand the issue, the TS definition looks correct, the version field is optional, so if set it must be a string otherwise omit it from the object altogether.

“optional” (with the ‘?’ sign) meaning it may be “undefined”. Which is so far so good. But the Go code does not allow “undefined” and will throw a TypeError (see my first post). Yet it does allow “null”. So there’s the difference!

You’re correct, I was not aware the ? operand would also allow the value itself to be undefined - a PR with a fix has been opened, will be part of the next release.

Thank you!

Usually, having a variable “undefined” in Javascript is the same as not having it in the object at all (“optional” so to say).
Seems that Go does treat that different. “null” and “undefined” are two separate things in JS/TS. I dont know how Go (i.e. the serializer) handles that internally.