Lua is misunderstood because it looks like superficially similar to a number of other languages but has a unique value proposition that is rarely well explained. The frustration that ensues from trying to use lua as though it is javascript or python or c is real. Because the value proposition isn't well explained, one has to use it and gain experience with it to appreciate it.

One of the key differentiators for lua is that it has multiple implementations that are both rock solid and will work on essentially any computer that you are likely to ever work with. Luajit is api compatible lua 5.1 (with a few 5.2 features backported). Lua 5.1 came out in 2006, which is to say that when writing lua 5.1 code, you are targeting a language that hasn't really changed in 15 years. This is incredibly liberating because you can trust that any code that you write in luajit or lua 5.1 is likely to work essentially forever (modulo security issues of course).

Lua is also one of the most simple languages out there. Pretty much everything that you need to know is in the reference documentation, which is a single file that you can easily download and store for offline use. It also hasn't changed in a decade and there is no reason to expect it will in the future.

Simplicity begets simplicity. As simple as lua is, you can make it even simpler by restricting yourself to a limited subset of the language. The more you restrict yourself, paradoxically the more liberated you are. You eventually realize that you can express any computational problem in lua. Lua provides an implicit vm that serves as an idealized model of a computer. It has numbers, strings, arrays and associative arrays (with a uniform syntax for both types of arrays). This is enough to do pretty much anything without too much pain. The lua runtime itself is fast enough to do most programming tasks faster than you can perceive. For the remaining tasks, you can just implement them in c and call them from lua. But you won't be writing normal c, you will be writing your own dialect of c that itself reflects lua. Many of the problems of c, particularly around memory management, are avoidable when the c code is explicitly designed to be embedded inside of a lua program.

Continuing on the theme of simplicity, lua is also one of the fastest scripting languages with respect to startup time (EDIT apologies for the poor formatting below but console output doesn't work great with HN):

bash-5.1$ time lua -e 'print "Hello, world!"'
Hello, world!

real 0m0.004s
user 0m0.002s
sys 0m0.002s

bash-5.1$ time python3 -c 'print("Hello, world!")'
Hello, world!

real 0m0.034s
user 0m0.024s
sys 0m0.007s

bash-5.1$ time node -e 'console.log("Hello, world!")'
Hello, world!

real 0m0.062s
user 0m0.049s
sys 0m0.011s

bash-5.1$ time ruby -e 'puts "Hello, world!"'
Hello, world!

real 0m0.086s
user 0m0.062s
sys 0m0.021s

The lua startup time is actually comparable to a standalone c executable:

bash-5.1$ time printf '#include <stdio.h>\nint main() { puts("Hello, world!"); return 0; }' | gcc -x c -o a.out - && ./a.out "on mac os, there are some checks that are run the first time a new exectuable is called so do one dry run before timing the results" > /dev/null; time ./a.out

real 0m0.074s
user 0m0.050s
sys 0m0.021s

Hello, world!

real 0m0.002s
user 0m0.001s
sys 0m0.001s

Comparing startup time may seem silly, but it raises the question how exactly you are benefiting from the excess complexity relative to lua that those other language runtimes have. You also can exploit the fast startup time to create a low latency development experience with minimal tooling. Configure your editor to save lua files with every keystroke. Then in a shell window, run something like:
> ls foo.lua | entr -c time lua foo.lua

You might be amazed by how much you can do in a lua script before the the latency becomes noticeable. By timing the results, you are also immediately aware of the impact on performance that any change to the script might have. This enables you to have an entirely different kind of development experience in which you are always fully aware of the state of your program because you are never waiting for compilation. The program either does what you expect it to, or it doesn't. No time is spent in the liminal state where one suspects the code may be correct (or incorrect), but you aren't really sure. You start realizing that if you organize your code in a certain way, you almost never have to wait more than say 100ms to get feedback.

On top of all that, if you don't like the syntax of lua, you can write a parser for another language in pure lua. Your new language, which will transpile to lua, will automatically inherit the good properties of the lua runtime.

Mastering lua will completely change the way that you think as a programmer and has the potentially to radically improve your experience of programming. Of course, once you have mastered lua the next step is to go beyond lua...