How do you convert an iPhone OSStatus code to something useful?

44,341

Solution 1

No. Not completely.

Some OSStatus are four-character-codes, so you can use (extracted from iPhone SDK's sample code "CAXException.h")

static char *FormatError(char *str, OSStatus error)
{
    // see if it appears to be a 4-char-code
    *(UInt32 *)(str + 1) = CFSwapInt32HostToBig(error);
    if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
        str[0] = str[5] = '\'';
        str[6] = '\0';
    } else {
        // no, format it as an integer
        sprintf(str, "%d", (int)error);
    }
    return str;
}

(See iOS/C: Convert "integer" into four character string for some more ways to convert fourcc into string, including Swift)

NSError's NSOSStatusErrorDomain is able to decode some OS errors. See @tomk's answer.

If you don't need to decode the number in program for the user, you may use the macerror script to manually find out the meaning, as mentioned in @lros's answer. The list of OSStatus supported can be found from its source code in /System/Library/Perl/Extras/5.18/Mac/Errors.pm.

There is also an online service http://osstatus.com/ collecting errors from all public frameworks. They are still not really complete e.g. the mapping to -12792 mentioned in the comment is missing. Probably it is a code from a private framework.

Solution 2

OSStatus is a signed integer value. You cannot convert or "cast" it to a string. You can convert it to a NSError like this:

NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:osStatus userInfo:nil];

Solution 3

This is available on macOS and for iOS from 11.3 and above.

I know this is an old post, but I was reading the apple docs in a section related to keychains. They mention a method that is used to convert OSStatus errors into something readable.

SecCopyErrorMessageString

Returns a string explaining the meaning of a security result code.

SecCopyErrorMessageString (OSStatus status, void* reserved );

Useage:

NSString* ErrMsg = (__bridge_transfer NSString *) SecCopyErrorMessageString(theOSStatusError, NULL);

It worked for me with my keychain OSStatus errors. Does it work for you? You will need Security.Framework added to your project to use this method.

Solution 4

I recently ran across another approach: the macerror command. Print out the OSStatus value as a signed integer. Then in a terminal window (on your Mac, not your iDevice!) type for example macerror -50. It will respond with a brief description. Obviously this is only helpful for you, during development.

Solution 5

Here is the code I wrote, hope it save you some typing... er, don't know how to make it show up correctly.

- (NSString *)OSStatusToStr:(OSStatus)st
{
    switch (st) {
        case kAudioFileUnspecifiedError:
            return @"kAudioFileUnspecifiedError";

        case kAudioFileUnsupportedFileTypeError:
            return @"kAudioFileUnsupportedFileTypeError";

        case kAudioFileUnsupportedDataFormatError:
            return @"kAudioFileUnsupportedDataFormatError";

        case kAudioFileUnsupportedPropertyError:
            return @"kAudioFileUnsupportedPropertyError";

        case kAudioFileBadPropertySizeError:
            return @"kAudioFileBadPropertySizeError";

        case kAudioFilePermissionsError:
            return @"kAudioFilePermissionsError";

        case kAudioFileNotOptimizedError:
            return @"kAudioFileNotOptimizedError";

        case kAudioFileInvalidChunkError:
            return @"kAudioFileInvalidChunkError";

        case kAudioFileDoesNotAllow64BitDataSizeError:
            return @"kAudioFileDoesNotAllow64BitDataSizeError";

        case kAudioFileInvalidPacketOffsetError:
            return @"kAudioFileInvalidPacketOffsetError";

        case kAudioFileInvalidFileError:
            return @"kAudioFileInvalidFileError";

        case kAudioFileOperationNotSupportedError:
            return @"kAudioFileOperationNotSupportedError";

        case kAudioFileNotOpenError:
            return @"kAudioFileNotOpenError";

        case kAudioFileEndOfFileError:
            return @"kAudioFileEndOfFileError";

        case kAudioFilePositionError:
            return @"kAudioFilePositionError";

        case kAudioFileFileNotFoundError:
            return @"kAudioFileFileNotFoundError";

        default:
            return @"unknown error";
    }
}
Share:
44,341
matt
Author by

matt

Updated on July 05, 2022

Comments

  • matt
    matt almost 2 years

    I am getting more than a little sick of this iPhone SDK and its documentation...

    I am calling AudioConverterNew

    in the documentation under Returns: it says "returns a status code" ... really...

    so far, through playing around with the parameters I have only been able to get two different errors neither of which are listed at the bottom of the Audio Converter reference.

    they are 'mrep' and '?tmf' (casting the OSStatus to a char array) but the specific codes aren't really the point.

    as far as I can tell, random error codes are defined in random files, so you can't just search one file, I can't find a help document that just lets you search for an error code to get more info, and from what I can tell, in OS X you can use GetMacOSStatusErrorString() to convert an error to something useful, but there is no iPhone equivalent?

    any help would be greatly appreciated.

    EDIT:

    ok, so casting them gives them in reverse (something I checked for 'mrep' but was not there either way round) , fmt? is in the list for the Audio Converter api, and is pretty self explanatory if a bit vague, but fair enough, still 'perm' isn't there (although it might be something to do with the simulator not supporting aac decoding) and my general question still stands.

  • DarkDust
    DarkDust over 13 years
    That will result in a nice crash if there is no 0 byte following on the stack soon.
  • coneybeare
    coneybeare over 12 years
    This generates a compiler warning: "Function call argument is an uninitialized value" on the if conditional line
  • tomk
    tomk almost 12 years
    Don't you think, if the developer who invented OSStatus wanted it to be a string he would declare it as one and not as a signed integer? You cannot or at least sholud not "cast" an integer to a string.
  • kennytm
    kennytm almost 12 years
    @tomk: (1) Did you realize this piece code comes from the official Apple sample codes? (2) How could you be sure that the developer invented OSStatus does not want to use the 4 bytes as a compact way to store 4 characters? I'm certain this is true, because OSType originates from the Mac OS.
  • tomk
    tomk almost 12 years
    I have to admit, I only found it afterwards. But as you wrote, "...some OSStatus are four...". "mrep" and "?tmf" really don't sound like proper error codes. See my answer for a public function to convert OSStatus to an error string.
  • kennytm
    kennytm almost 12 years
    @tomk: That's because you read them backwards. They are perm (perm-ission error) and fmt? (wrong f-or-m-a-t). Does you public method show "permission error" and "wrong format" or just "The operation couldn't be completed."? BTW the method in this answer is public too, just that it's not accomplished in a single line.
  • Martin Konicek
    Martin Konicek almost 12 years
    You would use printf("%d", err).
  • Per Johansson
    Per Johansson over 11 years
    The question is old but I'd say this is the correct answer. You can then get a descreptive string, e.g. 2012-11-05 22:28:52.338 foo[7300:707] Error Domain=NSOSStatusErrorDomain Code=-43 "The operation couldn’t be completed. (OSStatus error -43.)" (fnfErr: File not found)
  • fishinear
    fishinear almost 11 years
    You cannot get anything beyond "The operation couldn't be completed" for many errors this way. A combination of this answer and the accepted one works great.
  • quellish
    quellish almost 11 years
    Unfortunately, SecCopyErrorMessageString does not exist on iOS.
  • Randall Cook
    Randall Cook over 10 years
    Not even the presence of Jon Skeet on planet Earth is enough to make this answer right!
  • trojanfoe
    trojanfoe almost 10 years
    Use a macro and stringify and save even more typing.
  • inorganik
    inorganik almost 9 years
    This is helpful, though you should add a case for 0, which means no error.
  • Earlz
    Earlz over 8 years
    This seems to return "unknown error code" for the vast majority of error codes
  • Just a coder
    Just a coder over 8 years
    understood. i'll leave this up incase its helpful to someone on Mac
  • humblehacker
    humblehacker over 8 years
    This doesn't work on iOS 9 (I haven't tried any other versions) because [NSBundle bundleWithIdentifier:@"com.apple.security"] returns nil.
  • Anton Tropashko
    Anton Tropashko about 8 years
    it could not grok -34018
  • Sam
    Sam almost 8 years
    in swift it does not give anything relevant for code -12792, I've also tried for some other codes but nothing..
  • Sam
    Sam almost 8 years
    @kennytm how would that translate into swift? I've been trying to get more details on error code -12792 but did not manage to find more about it..
  • DEADBEEF
    DEADBEEF about 7 years
    What's the equivalent of CreateTypeStringWithOSType in Swift? I don't manage to use it...
  • DEADBEEF
    DEADBEEF almost 7 years
    Unfortunately it doesn't work for all the OSStatus. For exemple it cannot print the error with Core Audio OSStatus
  • MandisaW
    MandisaW over 6 years
    This answer was useful, but the underlying problem of poor error documentation is still an issue. Hitting the OSStatus lookup site did the trick, but this is a lapse on Apple's part.
  • Jules
    Jules almost 6 years
    "You cannot convert or "cast" it to a string" ... you are aware that many of Apple's file formats and APIs use "4CC"s, which are sequences of 4 ASCII characters converted to an integer by concatenating them in big-endian order? (4CCs are also used in a variety of media file formats, and have therefore made their way into non-Apple OS media libraries, e.g. Windows DirectShow uses them to identify codecs). Which means that converting them to strings for display purpose is actually a very sensible thing to do with them.
  • Ashley Mills
    Ashley Mills over 5 years
    Great answer for iOS 11.3 and onwards
  • Darrell Root
    Darrell Root about 5 years
    Thanks for that. Here's the swift syntax: if let error: CFString = SecCopyErrorMessageString(status, nil) {
  • johndoe
    johndoe about 5 years
    It is included in iOS 11.3 and above.
  • kakyo
    kakyo almost 5 years
    Turns out that this API is not that useful: It simply prints out "OSStatus <the number>" for you, #$%&^*
  • Stanislav Pankevich
    Stanislav Pankevich over 4 years
    Thanks for the answer. The code is working but I was missing the errors related to the AVAudioRecorder. I have borrowed your code and added missing errors here: stackoverflow.com/a/58348781/598057. You can add them here as well.
  • KerCodex
    KerCodex over 4 years
    I am glad this was useful to you. Everybody should of course adjust the code for errors useful in their context.