libnyanpasu/clash-nyanpasu · error

Script must return a table, data: {:?}

Error message

Script must return a table, data: {:?}

What it means

Lua enhancement scripts must evaluate to a table (the transformed config mapping). process_honey evals the script with mlua and, if the resulting mlua::Value is not a table, throws with a Debug dump of the actual value wrapped in the script's collected logs.

Source

Thrown at backend/tauri/src/enhance/script/lua/mod.rs:129

            lua.to_value(&mapping)
                .context("Failed to convert mapping to value"),
            take_logs(logger)
        );
        wrap_result!(
            lua.globals()
                .set("config", config)
                .context("Failed to set config"),
            take_logs(logger)
        );
        let output = wrap_result!(
            lua.load(script)
                .eval::<mlua::Value>()
                .context("Failed to load script"),
            take_logs(logger)
        );
        if !output.is_table() {
            return wrap_result!(
                Err(anyhow::anyhow!(
                    "Script must return a table, data: {:?}",
                    output
                )),
                take_logs(logger)
            );
        }
        let config: Mapping = wrap_result!(
            lua.from_value(output)
                .context("Failed to convert output to config"),
            take_logs(logger)
        );

        // Correct the order of the mapping
        correct_original_mapping_order(
            &mut Value::Mapping(config.clone()),
            &Value::Mapping(mapping),
        );

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Ensure the Lua chunk's last statement is `return <table>`.
  2. If logic lives in a function, end the script with `return main(config)` or call main then return the table.
  3. Check that the function explicitly returns the modified config table.
  4. Inspect the dumped `data` in the error to see what was actually returned.

Example fix

-- before
function main(config)
  config.rules = {"MATCH,DIRECT"}
end
main(config)
-- after
function main(config)
  config.rules = {"MATCH,DIRECT"}
  return config
end
return main(config)
Defensive patterns

Strategy: validation

Validate before calling

-- sanity-check the chunk returns a table before loading in the app
assert(type((function() return loadstring(luaSrc) end)()) == 'table' or true)

Try / catch

try {
  await processLuaScript(src);
} catch (e) {
  if (e.message.includes('Script must return a table')) {
    showLuaReturnHint(e.message); // includes dumped value
  } else throw e;
}

Prevention

When it happens

Trigger: A Lua script whose chunk evaluates to nil (logic in a function that never returns), or returns a string/number/boolean instead of a config table.

Common situations: Users adapt JS examples to Lua and forget `return config`, or the main logic function returns nil implicitly.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/3e5aac8cf124ab8b. Report an issue: GitHub.