Mac Error Codes

The following will help you find what error codes mean. When run you enter an error number (include the minus sign if appropriate) and the script returns the explanation for that number if it was found. Note that starting up the script takes a little time because when launched the script searches you computer… so be patient initially.

Did you know that there were files on your computer that contain explanations about the error codes? I didn’t until I read the following. It explains all about error codes, error domains, and those files. The script reads those files and pulls out the information.
http://developer.apple.com/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorHandling/ErrorHandling.html

I’ve found that some error codes are listed in several of the files so some times you get several results back when you search… you’ll have to figure out which of the explanations is really the one meant for you. Often looking at the error domain will give you a clue.

Parsing and extracting the information from these files was difficult to say the least because many of them are formatted differently… so any improvements to the code are welcome.

you can find the latest script in post #9

Doesn’t always agree with this list that I dredged up several years ago (2005), but usually close:

I’m not sure what you’re saying. I’m pulling the information directly from the files found in /System/Library/Frameworks (and a few others). There’s no doubt that the files I’m using have the most correct and most up-to-date information. That’s what the Error Handling article I linked to talks about… that’s the actual source for the error codes and their description. The way I’m doing this should remain accurate over time as Apple makes changes to these files.

There can only be 2 errors with the way I’m doing this, 1) I’m not finding every error file or 2) I’m not parsing the error information properly. If you find a glaring mismatch then please look at the file where I found the information (I list the file in the results) and double check if I parsed the file correctly. Hopefully we can work out the best solution for parsing those files.

Didn’t mean to criticize at all, Hank – I’m amazed that a 4-year old list is still reasonably accurate compared to your script, not the opposite. I posted it to give folks some numbers to play with.

Good idea then Adam. That makes sense. I posted this just for the process of people being able to check my code so that we can optimize it. I’ve never seen my type of solution to finding error codes, I’ve only ever seen lists which as you mention become out-of-date over time.

If I find the energy (we’re in the midst of a very humid heat wave – at least by Canadian standards) I’ll write a script to run down my list, parse out the number, run your code (with the top modified) and compare results. See what’s changed. :wink:

This is a great piece of code for a similar purpose:

http://bitbucket.org/boredzo/error-lookup-tool/

Well, I’ve been doodling at this for a couple of days and have come up with the version below. The optimisations are mainly inconsequential alterations to the text handlers. The most interesting change, perhaps, is the use of the “find” shell script’s own parameters to do the filtering which was done by an AppleScript repeat in the original. (The repeat’s still there, though, to build the Carbon/Cocoa list.) I haven’t fooled with the process which reads the error files as I don’t understand it yet! :rolleyes:

I’m afraid the optimisations make no difference at all to the user experience! The initial search for the files still takes a few seconds.

-- This script will search the error code files on your computer
-- explanation about error code files was found here:
-- http://developer.apple.com/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorHandling/ErrorHandling.html


property errorNum : ""
global errorFilesList, errorFilesDomain, errorFilesNames

(*============= COMPILE A LIST OF ALL THE ERROR FILES FOUND ON YOUR COMPUTER =============*)
-- 3 lists are made in this section; errorFilesList, errorFilesDomain, and errorFilesNames

set errorFilesList to {"/usr/include/mach/kern_return.h", "/usr/include/sys/errno.h"}
set errorFilesDomain to {"Mach", "POSIX"}

-- find the errors.h files in the /System/Library/Frameworks directory
-- add them to the errorFilesList but filter out known unusable files and add Cocoa/Carbon for each in the errorFilesDomain list
-- the unusable files do not contain error code numbers at all so we ignore them
-- So: items in the /System/Library/Frameworks/ heirarchy whose names end (case-insensitively) with "errors.h" but do not end with "NSErrors.h" or "DRCoreErrors.h" and don't have "Python.framework" in their paths.
set errorFilesList to errorFilesList & paragraphs of (do shell script "find /System/Library/Frameworks/  -iname  \\*errors.h -and \\! \\( -name \\*NSErrors.h -or -name \\*DRCoreErrors.h -or -path \\*Python.framework\\* \\)")

repeat with k from 3 to (count errorFilesList)
	if (item k of errorFilesList ends with "MacErrors.h") then
		set end of errorFilesDomain to "Carbon"
	else
		set end of errorFilesDomain to "Cocoa"
	end if
end repeat

-- get the list of file names
set errorFilesNames to getFileNames(errorFilesList)

repeat
	(*============= GET THE ERROR NUMBER FROM THE USER =============*)
	repeat
		display dialog "This will use all of the error header files on your computer to locate an error code for you." & return & return & "Please enter the error code to find:" default answer errorNum with icon note buttons {"Cancel", "OK"} default button "OK" with title "Error Codes"
		set {errorNum, button_pressed} to {text returned, button returned} of the result
		if errorNum is not "" then
			try
				set numCheck to errorNum as number
				exit repeat
			on error
				display dialog "Please enter only numbers!" buttons {"OK"} default button 1
			end try
		end if
	end repeat
	
	set formattedError to ""
	repeat with theCounter from 1 to (count of errorFilesList)
		set thisFile to item theCounter of errorFilesList
		
		try
			(*============= GREP THE FILES FOR THE ERROR NUMBER =============*)
			if (item theCounter of errorFilesNames) is "kern_return.h" then
				-- kern_return.h has the error description on multiple lines so we need to get a bunch of lines after the error number
				if (errorNum as number) is greater than or equal to 0 then
					set cmd to "grep -w --after-context=20 " & quoted form of errorNum & space & quoted form of thisFile & " | grep -v " & quoted form of ("\\-" & errorNum) & " | /usr/bin/grep -wi --after-context=20 \"#define\""
				else
					set cmd to "grep -w --after-context=20 " & quoted form of ("\\" & errorNum) & space & quoted form of thisFile & " | /usr/bin/grep -wi --after-context=20 \"#define\""
				end if
				set tempVar to do shell script cmd
				set text item delimiters to "*/"
				set tempVar to item 1 of (text items of tempVar)
				set text item delimiters to ""
				set errorParas to {tempVar}
			else
				if (errorNum as number) is greater than or equal to 0 then
					set cmd to "grep -w " & quoted form of errorNum & space & quoted form of thisFile & " | grep -v " & quoted form of ("\\-" & errorNum)
				else
					set cmd to "grep -w " & quoted form of ("\\" & errorNum) & space & quoted form of thisFile
				end if
				
				set tempVar to do shell script cmd
				set errorParas to paragraphs of tempVar
			end if
			
			repeat with j from 1 to (count of errorParas)
				set errorText to item j of errorParas
				(*============= REMOVE MISC CHARACTERS FROM THIS RESULT AND FORMAT IT =============*)
				set {errorDef, errorDesc} to parse_error_data(errorText)
				set aFormattedError to displayFormat(errorDef, errorDesc, theCounter)
				set formattedError to formattedError & return & aFormattedError
			end repeat
		end try
	end repeat
	
	(*============= GIVE THE RESULTS A FINAL FORMAT AND DISPLAY THEM =============*)
	if formattedError is not "" then set formattedError to finalFormat(formattedError)
	
	-- display the results
	if formattedError is "" then
		display dialog "The error numbered " & errorNum & " could not be found" buttons {"Quit", "Search Again"} default button 2
		if button returned of the result is "Quit" then exit repeat
	else
		set finalErrorSting to "Results for error number  --->  " & errorNum & return & return & formattedError
		display dialog finalErrorSting buttons {"Quit", "Save Results", "Search Again"} default button 1
		set theButton to button returned of result
		if theButton is "Quit" then
			exit repeat
		else if theButton is "Save Results" then
			set saveFile to choose file name with prompt "Specify where you want the file saved." default name "untitled.txt"
			writeTo(finalErrorSting, saveFile, false, string)
			exit repeat
		end if
	end if
end repeat



(*===================== SUBROUTINES ===================*)
on writeTo(this_data, target_file, append_data, mode) -- append_data is true or false, mode is string etc. (no quotes around either)
	try
		set target_file to target_file as Unicode text
		if target_file does not contain ":" then set target_file to POSIX file target_file as Unicode text
		set the open_target_file to open for access file target_file with write permission
		if append_data is false then set eof of the open_target_file to 0
		write this_data to the open_target_file starting at eof as mode
		close access the open_target_file
		return true
	on error
		try
			close access file open_target_file
		end try
		return false
	end try
end writeTo

on parse_error_data(theString) -- Replaces remove_chars(theString, aChar).
	set errorDef to word 1 of theString
	if (theString contains "/*") then
		set {TIDs, text item delimiters} to {text item delimiters, "*"}
		set errorDesc to text item 2 of theString
		set text item delimiters to TIDs
		set b to 1
		repeat while (character b of errorDesc is space)
			set b to b + 1
		end repeat
		set e to (count errorDesc)
		repeat while (character e of errorDesc is space)
			set e to e - 1
		end repeat
		set errorDesc to text b thru e of errorDesc
	else
		set errorDesc to errorDef
	end if
	
	return {errorDef, errorDesc}
end parse_error_data

on getFileNames(theList_ofPaths)
	set z to {}
	set TIDs to text item delimiters
	set text item delimiters to "/"
	repeat with anItem in theList_ofPaths
		set end of z to text item -1 of anItem
	end repeat
	set text item delimiters to TIDs
	return z
end getFileNames

on displayFormat(errorDef, errorDesc, theCounter)
	set aFormattedError to "Error Domain: " & (item theCounter of errorFilesDomain) & return & "Error File Name: " & (item theCounter of errorFilesNames) & return & "Error Name: " & errorDef & return & "Error Description: " & errorDesc & return
	return aFormattedError
end displayFormat

on finalFormat(formattedError)
	set TIDs to text item delimiters
	set text item delimiters to return
	set formattedError to text from text item 2 to text item -2 of formattedError
	set text item delimiters to TIDs
	return formattedError
end finalFormat

That’s good Nigel, thanks. I’ve been playing around with spotlight for the last week so it’s in my mind. I think the fastest search would be to use spotlight. So I came up with a spotlight command to find the error files. I matched it to my original method and your revised method, and all 3 methods find the exact same files. Here’s the spotlight command and the script runs extremely fast now! After running 1 search subsequent searches are instantaneous. There must be some caching thing going on.

set filter to "(kMDItemDisplayName == \"Errors.h\"w || kMDItemDisplayName == \"mig_errors.h\") && kMDItemDisplayName != \"DRCoreErrors.h\" && kMDItemDisplayName != \"NSErrors.h\""
set errorFilesList to paragraphs of (do shell script "mdfind -onlyin /System/Library/Frameworks " & quoted form of filter)

And here’s the whole script now with the spotlight command. The formatting of the files is the crazy part. I have a hard time understanding it myself. Please optimize it if you can but it is fast as it is. I’m more interested in finding out if I made any mistakes… am I returning everything that needs to be returned? Because the code is so crazy I can’t be certain it’s 100% accurate.

-- This script will search the error code files on your computer
-- explanation about error code files was found here:
-- http://developer.apple.com/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorHandling/ErrorHandling.html


property errorNum : ""
global errorFilesList, errorFilesDomain, errorFilesNames

(*============= COMPILE A LIST OF ALL THE ERROR FILES FOUND ON YOUR COMPUTER =============*)
-- 3 lists are made in this section; errorFilesList, errorFilesDomain, and errorFilesNames

set errorFilesList to {"/usr/include/mach/kern_return.h", "/usr/include/sys/errno.h"}
set errorFilesDomain to {"Mach", "POSIX"}

-- add the Errors.h files in the /System/Library/Frameworks directory including the mig_errors.h file
-- the "w" option means filter by words where words are also denoted by transition from uppercase to lowercase too
-- this "w" option filters out almost all the unwanted "error.h" files like the ones in the "Python.framework" path 
-- we also remove DRCoreErrors.h and NSErrors.h because they don't have any error codes in them
set theFilter to "(kMDItemDisplayName == \"Errors.h\"w || kMDItemDisplayName == \"mig_errors.h\") && kMDItemDisplayName != \"DRCoreErrors.h\" && kMDItemDisplayName != \"NSErrors.h\""
set errorFilesList to errorFilesList & paragraphs of (do shell script "mdfind -onlyin /System/Library/Frameworks " & quoted form of theFilter)

-- add Cocoa/Carbon to errorFilesDomain for each file in errorFilesList
repeat with i from 3 to (count of errorFilesList)
	if (item i of errorFilesList) ends with "MacErrors.h" then
		set end of errorFilesDomain to "Carbon"
	else
		set end of errorFilesDomain to "Cocoa"
	end if
end repeat

-- get the list of file names
set errorFilesNames to getFileNames(errorFilesList)

repeat
	(*============= GET THE ERROR NUMBER FROM THE USER =============*)
	repeat
		display dialog "This will use all of the error header files on your computer to locate an error code for you." & return & return & "Please enter the error code to find:" default answer errorNum with icon note buttons {"Cancel", "OK"} default button "OK" with title "Error Codes"
		set {errorNum, button_pressed} to {text returned, button returned} of the result
		if errorNum is not "" then
			try
				set numCheck to errorNum as number
				exit repeat
			on error
				display dialog "Please enter only numbers!" buttons {"OK"} default button 1
			end try
		end if
	end repeat
	
	set formattedError to ""
	repeat with theCounter from 1 to (count of errorFilesList)
		set thisFile to item theCounter of errorFilesList
		
		try
			(*============= GREP THE FILES FOR THE ERROR NUMBER =============*)
			if (item theCounter of errorFilesNames) is "kern_return.h" then
				-- kern_return.h has the error description on multiple lines so we need to get a bunch of lines after the error number
				if (errorNum as number) is greater than or equal to 0 then
					set cmd to "grep -w --after-context=20 " & quoted form of errorNum & space & quoted form of thisFile & " | grep -v " & quoted form of ("\\-" & errorNum) & " | /usr/bin/grep -wi --after-context=20 \"#define\""
				else
					set cmd to "grep -w --after-context=20 " & quoted form of ("\\" & errorNum) & space & quoted form of thisFile & " | /usr/bin/grep -wi --after-context=20 \"#define\""
				end if
				set tempVar to do shell script cmd
				set text item delimiters to "*/"
				set tempVar to item 1 of (text items of tempVar)
				set text item delimiters to ""
				set errorParas to {tempVar}
			else
				if (errorNum as number) is greater than or equal to 0 then
					set cmd to "grep -w " & quoted form of errorNum & space & quoted form of thisFile & " | grep -v " & quoted form of ("\\-" & errorNum)
				else
					set cmd to "grep -w " & quoted form of ("\\" & errorNum) & space & quoted form of thisFile
				end if
				
				set tempVar to do shell script cmd
				set errorParas to paragraphs of tempVar
			end if
			
			repeat with j from 1 to (count of errorParas)
				set errorText to item j of errorParas
				
				(*============= REMOVE MISC CHARACTERS FROM THIS RESULT AND FORMAT IT =============*)
				set theChars to {return, tab, "*", "/", "#define", "=", ",", errorNum, space}
				repeat with aChar in theChars
					set errorText to remove_chars(errorText, aChar)
				end repeat
				
				set aFormattedError to displayFormat(errorText, theCounter)
				set formattedError to formattedError & return & aFormattedError
			end repeat
		end try
	end repeat
	
	(*============= GIVE THE RESULTS A FINAL FORMAT AND DISPLAY THEM =============*)
	if formattedError is not "" then set formattedError to finalFormat(formattedError)
	
	-- display the results
	if formattedError is "" then
		display dialog "The error numbered " & errorNum & " could not be found" buttons {"Quit", "Search Again"} default button 2
		if button returned of the result is "Quit" then exit repeat
	else
		set finalErrorSting to "Results for error number  --->  " & errorNum & return & return & formattedError
		display dialog finalErrorSting buttons {"Quit", "Save Results", "Search Again"} default button 1
		set theButton to button returned of result
		if theButton is "Quit" then
			exit repeat
		else if theButton is "Save Results" then
			set saveFile to choose file name with prompt "Specify where you want the file saved." default name "untitled.txt"
			writeTo(finalErrorSting, saveFile, false, string)
			exit repeat
		end if
	end if
end repeat



(*===================== SUBROUTINES ===================*)
on writeTo(this_data, target_file, append_data, mode) -- append_data is true or false, mode is string etc. (no quotes around either)
	try
		set target_file to target_file as Unicode text
		if target_file does not contain ":" then set target_file to POSIX file target_file as Unicode text
		set the open_target_file to open for access file target_file with write permission
		if append_data is false then set eof of the open_target_file to 0
		write this_data to the open_target_file starting at eof as mode
		close access the open_target_file
		return true
	on error
		try
			close access file open_target_file
		end try
		return false
	end try
end writeTo

on remove_chars(theString, aChar)
	set {TIDs, text item delimiters} to {text item delimiters, aChar}
	set a to text items of theString
	set b to {}
	repeat with i from 1 to (count of a)
		if item i of a is not "" then
			set end of b to item i of a
		end if
	end repeat
	set text item delimiters to space
	set c to b as text
	set text item delimiters to TIDs
	return c
end remove_chars

on getFileNames(theList_ofPaths)
	set z to {}
	set text item delimiters to "/"
	repeat with anItem in theList_ofPaths
		set end of z to (item -1 of (text items of anItem))
	end repeat
	set text item delimiters to ""
	return z
end getFileNames

on displayFormat(a, theCounter)
	set text item delimiters to space
	set b to text items of a
	set errorDef to item 1 of b
	try
		set errorDesc to (items 2 thru -1 of b) as text
	on error
		set errorDesc to errorDef
	end try
	set text item delimiters to ""
	set aFormattedError to "Error Domain: " & (item theCounter of errorFilesDomain) & return & "Error File Name: " & (item theCounter of errorFilesNames) & return & "Error Name: " & errorDef & return & "Error Description: " & errorDesc & return
	return aFormattedError
end displayFormat

on finalFormat(formattedError)
	set text item delimiters to return
	set b to text items of formattedError
	set b to items 2 thru -2 of b
	set formattedError to b as text
	set text item delimiters to ""
	return formattedError
end finalFormat

Yep. That’s certainly faster! :slight_smile:

I had to change filter to |filter| to avoid a clash with a Satimage command.

Yes it is! I can’t believe I didn’t do this earlier. I use this script fairly frequently and it was always a pain to wait for it to open. BTW, I changed filter to theFilter in the above script to make sure no one else runs into that problem. Thanks.

VERY nice script!

I found this page from a web search and felt inclined to try it, but it did not work. I searched my drive and had no header files! It turns out Mavericks does not install them by default… and this was an upgrade from ML.

Taking a hint from http://stackoverflow.com/questions/19580758/gcc-fatal-error-stdio-h-no-such-file-or-directory I used Xcode and ran the

xcode-select --install

command to install them. The script now works without changes!

I do suggest trying this with a fresh Mavericks install and catching this as an error with a solution message… I don’t have another Mac right now so I can’t do it.

thanks,

chris

Thanks for updating this topic, Chris!