Issues when calling exported client function

I want to export a client function from my resource to be able to use it from other resources.

When the player joins the game, the resource cannot find the exported functions:

[ 47797] Error resuming coroutine: citizen:/scripting/lua/scheduler.lua:699: No such export MyExportedFunction in resource bob74_export
[ 47797] stack traceback:
[ 47797] [C]: in function ‘error’
[ 47812] citizen:/scripting/lua/scheduler.lua:699: in metamethod ‘__index’
[ 47812] client.lua:2: in function <client.lua:1>

If I restart the import resource (bob74_import) from the server console, it finds the function and return the value in the console as expected.
If I disconnect and reconnect the game, I come back to the same issue (No such export MyExportedFunction in resource...).

Since I was unable to get it to work properly, I stripped it to this test environment:

  • Latest server version and server data
  • Brand new server.cfg
  • Server cache deleted
  • Only two resources added (and loaded in this order):
    bob74_export
    bob74_import
  • The point is to get a table from another resource and show one of its values using Citizen.trace()

bob74_export


__resource.lua:

resource_manifest_version '05cfa83c-a124-4cfa-a768-c24a5811d8f9'

client_script 'client.lua'
export 'MyExportedFunction'

client.lua:

function MyExportedFunction()
    return {value = "==========> My value"}
end

bob74_import


__resource.lua:

resource_manifest_version '05cfa83c-a124-4cfa-a768-c24a5811d8f9'

client_script 'client.lua'

client.lua:

Citizen.CreateThread(function()
    --I also tried: ImportedValue = exports['bob74_export']:MyExportedFunction()
    ImportedValue = exports.bob74_export:MyExportedFunction()
    Citizen.Trace(ImportedValue.value)
end)

Can you tell me what am I doing wrong?
It seems pretty simple, I don’t understand why it doesn’t work on connection.

Wait like 1000ms before calling the export. Also try to set in your bob74_import __resource.lua a dependency for the bob74_export

Thanks! I added a dependency into the import resource (dependency 'bob74_export') but it still didn’t work.
Waiting before retrieving the exported function works well but it seems to be quite a messy way to do.

Aren’t there any reliant way to do this? I was really hopping adding a dependency would do the trick, otherwise I don’t see its purpose.

I have always had to do this when calling a export early in the server start as it takes a moment for the exports to be ready.

You could also maybe use a timeout instead of a Citizen.Wait()?

1 Like

Alright, I guess they will change this behaviour later ^^

Thanks for your answers, using a timeout looks like a nice solution to keep things clean :slight_smile:

EDIT:
This should work fine:

local ImportedValue = nil

Citizen.CreateThread(function()
    local errorMsg = ""
    
    -- Try to read each 250ms and timeout after 5 seconds
    for i = 0, 20, 1 do
        local status

        -- Calling the function in protected mode
        status, errorMsg = pcall(function() ImportedValue = exports['bob74_export']:MyExportedFunction() end)
    
        if status then
            break
        end
        
        Citizen.Wait(250)
    end

    if (ImportedValue == nil) then
        Citizen.Trace("ERROR: " .. errorMsg)
        return
    end
    
    Citizen.Trace(ImportedValue.value)
end)

No problem. Have a nice rest of your day.

Don’t use export in your resource manifest, but use the exports(…) function when defining it.

See also: https://docs.fivem.net/scripting-manual/runtimes/lua/#using-exports

1 Like

Ah. Didn’t even know that there was another method of handling exports… Would have been nice to know this a while ago.

I find it easier to see what functions are available from the resource when it is listed in the manifest. Is there a difference between the exports function and using export in the manifest?

Also, I noticed this part:

Note that these exports will only be available after the first scheduler tick

It could explain why I’m unable to call the method as soon as the resource is loaded.

Yes, the exports function registers the export immediately.

1 Like

I just did some tests and you’re totally right!

Using exports(), I can call my functions immediately whereas using export 'MyFunction', it is only available after the next tick (using Wait(0))
That’s the “after the first scheduler tick” part of the documentation I guess. I didn’t get it last time.

Thanks a lot to all of you, it is a lot clearer now :slight_smile:

1 Like