This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Communeguy's profile picture

[ERROR]attempt to concatenate string and nil

Started by Communeguy, 23 November 2014 - 06:48 PM
Communeguy #1
Posted 23 November 2014 - 07:48 PM
Hello guys.

I'm currently building a program suite. One of the programs, CGAdmin, is a program meant to handle a set of tables (various flavours of user credential), which it passes back and forth with a server.

I've spent a fair amount of time purging syntax errors and other minor problems from the code, but after several hours and some attempts at solving the error "attempt to concatenate string and nil" which is being thrown by textutils at line 177. Line 177 is in some code I borrowed that was available for use - I attributed gravityscore who originally posted it to the forums. Code is in many lines, so I've put it in the spoiler.

((Yes, I know it's inelegant. I'm a noob.))

edit: After repeated attempts and frequently posting the wrong code for reasons passing understanding, the code can be found here: http://pastebin.com/k1u5zTd4#
Edited on 23 November 2014 - 06:53 PM
valithor #2
Posted 23 November 2014 - 08:07 PM
Hello guys.

I'm currently building a program suite. One of the programs, CGAdmin, is a program meant to handle a set of tables (various flavours of user credential), which it passes back and forth with a server.

I've spent a fair amount of time purging syntax errors and other minor problems from the code, but after several hours and some attempts at solving the error "attempt to concatenate string and nil" which is being thrown by textutils at line 177. Line 177 is in some code I borrowed that was available for use - I attributed gravityscore who originally posted it to the forums. Code is in many lines, so I've put it in the spoiler.

((Yes, I know it's inelegant. I'm a noob.))

edit: After repeated attempts and frequently posting the wrong code for reasons passing understanding, the code can be found here: http://pastebin.com/k1u5zTd4#

Could you please post the full error message you are receiving. The error is not on line 177 of your program, but what is in line 177 of the textutils api. This means that you are using something wrong.
Dragon53535 #3
Posted 23 November 2014 - 08:16 PM
Nothing on either program could possibly cause that error on line 177.
Line 177 of your code:

for j = 17, 64 do
Line 177 of the textutils API:

local sEntry
As Valithor suggested perhaps you could post the full error message.
Communeguy #4
Posted 23 November 2014 - 08:45 PM
Full error code follows:

textutils:177: attempt to concatenate string and nil.

As you could probably tell from the code, 177 is from the written block I'm re-using.
In terms of "when", the error seems to be throwing somewhere between 243 and 247. My bet is on line 246.

That is to say, the admin program does correctly print "Server authentication complete." when it is meant to, and then pops the error above.
Edited on 23 November 2014 - 07:48 PM
valithor #5
Posted 23 November 2014 - 11:36 PM
Full error code follows:

textutils:177: attempt to concatenate string and nil.

As you could probably tell from the code, 177 is from the written block I'm re-using.
In terms of "when", the error seems to be throwing somewhere between 243 and 247. My bet is on line 246.

That is to say, the admin program does correctly print "Server authentication complete." when it is meant to, and then pops the error above.

Check to see if message is nil I am unable to test it myself.

If message is not nil, then if you are not running cc v. 1.65 could you pastebin the textutils API. That will help find exactly what function is causing the error.

Nothing on either program could possibly cause that error on line 177.
Line 177 of your code:

for j = 17, 64 do
Line 177 of the textutils API:

local sEntry
As Valithor suggested perhaps you could post the full error message.

That likely means he is on a older version of cc, which has a slightly different textutils API.
Edited on 23 November 2014 - 10:39 PM
theoriginalbit #6
Posted 24 November 2014 - 02:04 AM
Okay so valithor is incorrect, your problem isn't with the textutils API. If you take a look at textutils you'll notice that line 177 is within the textutils.unserialize function


function unserialize( s )
  local func, e = loadstring( "return "..s, "serialize" ) --# specifically this line
  if not func then
    return s
  else
    setfenv( func, {} )
    return func()
  end
end

this function has not changed since the start of ComputerCraft, therefore it cannot be a problem with textutils, instead a problem with your program.

You invoke textutils.unserialize 4 times, if we assume the messages you're receiving exist (as the Modem API relies on it) then you're left with line 218 (your load function). I'd say chances are your file has no contents.

I suggest you confirm exactly where the cause of your error is, add this code to the top of your program

local old = textutils.unserialize
function textutils.unserialize( s )
  if type(s) ~= "string" then
    error( "you're not giving it a string here", 2)
  end
  return old( s )
end

and this to the bottom

textutils.unserialize = old

and it will tell you where your problem is occurring.
valithor #7
Posted 24 November 2014 - 03:15 AM
-snip

I fail to see how I was wrong maybe my wording was difficult to understand, or you thought I meant something else. I said/meant that his problem was not on line 177 of HIS problem (since that is where he was looking) but actually was coming from line 177 of textutils API. This means that it has to occur at whatever code was run which invokes line 177 of textutils API, which happens to be textutils.unserialize. I would also like to point out that you pointed out basically the same thing as I did (that message is nil) but just provided a workaround.

If I completely missed something here then please tell me, but I really do not think I was incorrect other than the fact that the API has not changed.
Bomb Bloke #8
Posted 24 November 2014 - 04:03 AM
If this helps clarify matters, the "error message" is being triggered at line 177 of textutils, but that's not where the "problem" is - the "problem" is he gathers and then passes invalid data to the textutils API. While I know you understand that, your choice of words wasn't ideal.

BIT's code isn't a "workaround" - by messing with the error level, it should generate an error on the line where the incorrect data is being passed.

Though given that the script prints "Server authentication complete." directly before erroring out, it sounds like we already know where that trigger is - I'd stick some print statements in prior to line 246, printing the types and contents of event, message, replyChannel, etc. You'll need to spread them across multiple lines (as attempting to join them together into one print statement will likely just generate further concatenation errors instead).
Edited on 24 November 2014 - 03:06 AM
Communeguy #9
Posted 24 November 2014 - 08:44 PM
Thanks everyone. The Original Bit's code confirmed that the error was due to bad sends from the server. That's since been rectified and now I'm on to busting other problems stemming from bad design on the server.
Edited on 24 November 2014 - 07:58 PM
theoriginalbit #10
Posted 24 November 2014 - 11:04 PM
I could have sworn that just the other week when I was testing some things that the modem.transmit function didn't allow nil for the message. but I'm glad you've fixed it now.
Communeguy #11
Posted 25 November 2014 - 12:08 AM
I think something about the server code was changing the messages from strings, to tables, and then deleting them, rendering them nil. Either way, that's fixed now.

In fact, I have a whole new set of problems. After futzing around and discovering my random numbers were too big (I have since reduced them), I now have a most peculiar error with no message at all. The revised code is at http://pastebin.com/k1u5zTd4, and the nature of the failure is as follows:

>admin
-Program begins the way it should (asking for the "input" variable that it sends to the server.)
-The server accepts the valid input and sends back its own verification code, then a chain of messages back and forth transfers over the tables that make up the database the admin program is meant to be managing.
-All of the prints on the terminal running the admin program reflect success. They persist for about 1 second, and then the program exits.

I can't tell what I've done wrong, but the code seems to be skipping the actual functional part of the program (the IF tree beginning on 247), directly down to the end, and then terminating without being told to.
Bomb Bloke #12
Posted 25 November 2014 - 12:49 AM
You've got your "access" variable localised to a spot where line 274 can't "see" it.
Communeguy #13
Posted 25 November 2014 - 01:26 AM
Ah, herp. I thought local restricted the variable to the program, not what it actually does. To fix.

Something I already know will be a problem is the way I am storing the passwords as salted hashes. The current code won't work (the program hasn't got that far without crashing yet anyway so no error message.) Because the current code is adding two strings together.what is the correct method of adding a salt to a password for storage? Append it before hashing? No code, please. I want to learn the theory first.

My operating idea is to have the admin program concatenate the unhashed salt and password together, and then save them to the table on the server. Then any program that uses this standard would check a password concatenating the (unhashed) salt it was provided with, the password the player entered, and comparing it to the password entry for the username provided. That should work, right?
Edited on 25 November 2014 - 01:23 AM
theoriginalbit #14
Posted 25 November 2014 - 02:05 AM
local restricts the variable to the scope it is within

local function a() --# only accessible by the program and any child scopes
  print("hi")
end

a() --# works

local function b()
  a() --# also works
end

local function c()
  local d = "hi" --# only accessible by this scope and children scopes
  print(d) --# works
end

print(d) --# doesn't work

Lua even contains a structure that allows for scope reduction

do
  local d = "hello world"
  print(d) --# works
end

print(d) --# doesn't work

Lua-users Scope Tutorial
Bomb Bloke #15
Posted 25 November 2014 - 04:18 AM
what is the correct method of adding a salt to a password for storage? Append it before hashing? No code, please. I want to learn the theory first.

To the best of my understanding, you get the user to enter the new password, then generate a unique random salt ("random" as in "entirely unrelated to what the user entered" - don't try to use the password as the seed!). Concatenate the two and hash the result. Save this hash, along with the unhashed salt, to the server.
theoriginalbit #16
Posted 25 November 2014 - 04:32 AM
I have some write-ups on salting scattered around these forums, lets see what I can quickly find for you;
Edited on 25 November 2014 - 03:32 AM
Communeguy #17
Posted 25 November 2014 - 09:10 PM
Thanks for the input, guys. :)/>

With the updated code http://pastebin.com/k1u5zTd4, I've fixed the localization issue, and I've tested the REM functional group by manually adding users on the server-side, all but hard-coding them into the system. I'm now working on debugging the ADD tree (from 298-317), which had some problems, most of which I was able to fix. Now, it simply crashes at 306, with no error message given, simply reverting to the default command prompt of CraftOS.

I've determined the area of the crash to be around 306 by inserting a few print commands around the code, since removed, and seeing which ones did and didn't appear. The last one to print correctly was at line 306. The next one would have been between 314-315.
I'm reasonably convinced the bad code is how I'm doing the table lookup. Tables aren't my strong point. I BELIEVE I'm using the code correctly, but I also believe it's probably bad.

The code I THINK is bad, specifically:

  for k,v in pairs(userHash) do
									    if v == user then
																			    return k
									    guid = k
									    end
							    end	
KingofGamesYami #18
Posted 25 November 2014 - 09:16 PM
Just looking at your loop, setting a variable after returning definitely won't work: When return is called, the function ends.
Dragon53535 #19
Posted 25 November 2014 - 09:18 PM
Remove that "return k" line and you should be good.
Since you're not in a function returning quits the script and returns to what called it. In this case the shell.
Communeguy #20
Posted 25 November 2014 - 09:29 PM
Ah. Thanks much. That completely cleared it.
Edited on 25 November 2014 - 08:55 PM