Error when registering functions in another resource + Repro resource

I had a few clients come to me with a default lua error message that is just stating SCRIPT ERROR: error object is not a string without any sort of stack trace or line number at all.
I have managed to pinpoint this issue and even build a reproduction resource and a workaround (at least for my case).

  • The issue happens when you have two scripts where one is the dependency (“resource1”) of the other one (“resource2”). (happens on both server and client)
  • resource1 has an export that takes a function and adds it to a table that can later be iterated over and executes all functions that have been registered.
  • resource2 simply registers a function to resource1.
  • when calling the table iteration function, all functions will be executed
  • if you now restart resource2 it will register that same function again
  • when you now call the table iteration function, either nothing happens or the mentioned error SCRIPT ERROR: error object is not a string appears (this seems to only be the case if it is a complex function that is being registered)

Of course it makes sense, that it doesn’t work properly simply because the “old” function is now missing but still being referenced in the function table. But it is not at all apparent as to why it is happening which makes backtracing it extremely annoying.

Client (production/canary) and FXServer version

Client: Beta, Gamebuild 2372
Server: latest recommended, 5181

What you expected to happen

Error stack trace or proper error message in general

What actually happens

Nothing or SCRIPT ERROR: error object is not a string without stack trace

Workaround

Use luas protected function call pcall when calling the functions to determine if they have this problem.

Reproduction steps:

  • Download the example resources ReproTest.zip (1.6 KB)

  • Enter ensure ReproTest1 and ensure ReproTest2 in console

  • Enter call command, message Doing something on server/client... should appear

  • Enter ensure ReproTest2 in console

  • Enter call command again, nothing or error message appears

  • Enter pcall command, message appears again

server side:

cfx> ensure ReproTest1
[ citizen-server-impl] Stopping resource ReproTest1
[    c-scripting-core] Creating script environments for ReproTest1
[ citizen-server-impl] Started resource ReproTest1
cfx> ensure ReproTest2
[ citizen-server-impl] Stopping resource ReproTest2
[    c-scripting-core] Creating script environments for ReproTest2
[ citizen-server-impl] Started resource ReproTest2
cfx> call
[   script:ReproTest2] Doing something on server...
cfx> pcall
[   script:ReproTest2] Doing something on server...
cfx> ensure ReproTest2
[ citizen-server-impl] Stopping resource ReproTest2
[    c-scripting-core] Creating script environments for ReproTest2
[ citizen-server-impl] Started resource ReproTest2
cfx> call
cfx> pcall
[   script:ReproTest2] Doing something on server...
cfx>

client side:

If necessary, I can also send in the two resources that actually produce the SCRIPT ERROR: error object is not a string error, but especially the dependency is fairly complex by now.

Making this explicitly emit an error in cases where it currently does not would break compatibility since errors unwind, and some scripts may be relying on calling a ‘dead’ function reference being a no-op.

The other error is misleading, rather, but you of course haven’t provided a repro for such, so it’s hard to tell what causes that, may be entirely unrelated to the first issue.