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

[Error] “attempt to index ? (a nil value)” on fs API file.write() [IC2 Reactor Controller]

Started by Swiss Cheese Knife, 03 November 2012 - 05:08 AM
Swiss Cheese Knife #1
Posted 03 November 2012 - 06:08 AM
I have written a simple program to automatically refill my IC2 reactor. In case of the server going offline the program saves state so it can be resumed with an autorun script when the server is restarted.

The program loops in the following manner:
For the countdown
Wait one second
Decrement the countdown
Write the new value for the countdown to disk
Repeat

The program almost works flawlessly, the refill routine works perfectly, having been tested several times, and for the majority of the time so does the main loop. The problem is that every few hundred seconds the computer will crash with the following error: “reactor:13: attempt to index ? (a nil value)”. This error is indicated to come from the fs API file.write() function.

I have tried all I can think of to fix the problem:
  • Originally the program was written with the io API, swapping between the two has made no difference.
  • I have tried saving state every 5 seconds instead in order to give the computer more time to write, but the problem persists.
  • I have put the sleep before and after write in the loop, but this has not helped.
  • I looked around in the lua io documentation and tried to change the buffering mode, but the function did not seem to be available in computercraft.
The only other thing I can think of is that the sleep stops the write from completing before it is called again. My thoughts would be to write in some kind of multithreading/whatever the lua equivalent is, but that seems like it would need a fairly large re-write.

I thought that I ought to check that it is not something simple I am missing before I try the above solution.


--FUNCTIONS
function readCache() --Read the time stored on disk
	local cache = fs.open("disk/cache", "r")
	local time = cache.readAll()
	cache.close()

	return tonumber(time)
end
function writeCache(Str) --Write the value of the countdown to disk
	local cache = fs.open("disk/cache", "w")
	cache.write(Str)
	cache.close()
end
function clearTerm() --Clear terminal and reset cursor
	term.clear()
	term.setCursorPos(1, 1)
end
function refill() --Refill reactor
	clearTerm()
	write("Disengaging reactor and cooling: ")
rs.setOutput("back", true)
sleep(0.1) --No reason for this other than to make it look the part
	print("Done\n")
	sleep(0.75)
	for i = 1, 47 do --47 fuel cells in the reactor
		clearTerm()	  
		write("Emptying reactor: ")
		write(math.ceil((i/47)*100))
		write("%")
		rs.setOutput("right", true) --Could make these sleeps smaller, but the server connection is not rock solid, better safe than sorry
		sleep(0.5)
		rs.setOutput("right", false)
		sleep(0.5)
	end
	clearTerm()
	write("Emptying reactor: Done")
	sleep(0.75)
	for i = 1, 47 do
		clearTerm()
		write("Filling reactor: ")
		write(math.ceil((i/47)*100))
		write("%")
		rs.setOutput("left", true)
		sleep(0.5)
		rs.setOutput("left", false)
		sleep(0.5)
	end
	clearTerm()
	print("Filling reactor: Done")
	sleep(0.75)
	clearTerm()
	write("Reinitialising reactor and cooling: ")
rs.setOutput("back", false)
sleep(0.1)
	print("Done\n")
	sleep(0.75)
end
--IN POINT
while true do
  
	local loop = readCache() --Set 'loop' to the stored remaining time
	clearTerm()
	write("Resuming reactor from ")
	write(loop)
	for i = 1, loop do
		sleep(1)
		writeCache(loop - i)
		clearTerm()	  
	  
		write("Next refill in ")
		print(loop - i)
	end
	refill()
	writeCache(10000) --Set cache to 10000 seconds, time for reactor to cycle, may need adjusting but approximately this value
end
remiX #2
Posted 03 November 2012 - 06:27 AM
Have you tried re-downloading the api file?
ChunLing #3
Posted 03 November 2012 - 03:59 PM
Put the "print(loop-i)" before the call to your writecache function. That way you can have a better idea what you were trying to write. You also might want to be explicit in your conversions from string to number and back.