How to capture stderr from a macOS GUI app (UIKit/AppKit) when launched via open or Finder?

For a macOS GUI application (with a UIKit or AppKit entry point), I want to reliably capture diagnostic logs sent to stderr — especially useful when the app is launched from a terminal script or runs in the background, and traditional GUI elements (like alert dialogs) may not be viable. This is to log startup failures or even success messages for later inspection. However, when the app is launched via open MyApp.app, stderr redirection like open MyApp.app 2> log.txt does not capture any output — the file is created, but remains empty.

The only way I can capture stderr reliably is by bypassing the bundle and directly launching the binary inside with ./MyApp.app/Contents/MacOS/MyApp 2> ~/log.txt

This logs as expected, but is not the user-friendly or typical way to launch apps on macOS. Double-clicking the app in Finder also does not show any stderr output.

Is there any recommended or supported way to redirect or access stderr output when launching a .app bundle via open, or any best practice for logging critical failures from a GUI app when terminal output isn't visible?

Answered by DTS Engineer in 842025022

If this is an app you’re developing then you can do this redirect in the app. Add a debug option that causes the app to open your log file and dup2 it on to stderr (technically STDERR_FILENO).

Having said that, logging to stderr isn’t best practice on the Mac because, by default, stderr goes nowhere. So, lemme answer this from your original post:

any best practice for logging critical failures from a GUI app when terminal output isn't visible?

I generally recommend that you log to the system log. See Your Friend the System Log for links to documentation and other resources.

And that brings me to this:

The idea is that if something goes wrong, the user or support team can rerun the app from a terminal

If you log to the system log, this re-run step isn’t necessary. The user can immediately trigger a sysdiagnose, which snapshots the system log, and you can debug based on that.

Now, you don’t have to use this. It’s fine to invent your own logging infrastructure if the system log doesn’t work for you. However, doing logging correctly is hard, so you should at least understand what the sytem log can do before you decide not to use it (-:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Is this an app that you control? Or are you trying to do this for apps made by other developers? Or indeed apps built in to the system?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@DTS Engineer It's the first one, it is an app that I control as a developer.

These apps will log to stderr due to ungraceful exit. The idea is that if something goes wrong, the user or support team can rerun the app from a terminal, and they’ll see the error on the console or redirected to a file or any other way.

If this is an app you’re developing then you can do this redirect in the app. Add a debug option that causes the app to open your log file and dup2 it on to stderr (technically STDERR_FILENO).

Having said that, logging to stderr isn’t best practice on the Mac because, by default, stderr goes nowhere. So, lemme answer this from your original post:

any best practice for logging critical failures from a GUI app when terminal output isn't visible?

I generally recommend that you log to the system log. See Your Friend the System Log for links to documentation and other resources.

And that brings me to this:

The idea is that if something goes wrong, the user or support team can rerun the app from a terminal

If you log to the system log, this re-run step isn’t necessary. The user can immediately trigger a sysdiagnose, which snapshots the system log, and you can debug based on that.

Now, you don’t have to use this. It’s fine to invent your own logging infrastructure if the system log doesn’t work for you. However, doing logging correctly is hard, so you should at least understand what the sytem log can do before you decide not to use it (-:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

Expanding on what Quinn said, I did what to explain what's actually going on here as the answer is that, ironically, macOS is basically acting the same way most Unix system would. Let me start here:

The only way I can capture stderr reliably is by bypassing the bundle and directly launching the binary inside with ./MyApp.app/Contents/MacOS/MyApp 2> ~/log.txt

This works because your primary executable is being run in the same way any other Unix tool is.

However, when the app is launched via open MyApp.app, stderr redirection like open MyApp.app 2> log.txt does not capture any output — the file is created, but remains empty.

This fails for two reasons:

  1. (minor) What open actually does ask LaunchServices to run your app, making launchd the parent process of your app.

  2. (major) You didn't tell "open" to reroute stderr/in/out so it didn't. From the open man page:

--stdin PATH
 Launches the application with stdin connected to PATH.

--stdout PATH
 Launches the application with stdout connected to PATH.

--stderr PATH
 Launches the application with stderr connected to PATH.

Double-clicking the app in Finder also does not show any stderr output.

The Finder is actually doing the same thing "open" does, except it doesn't allow you to specify the same range of options.

In terms of your questions here:

Is there any recommended or supported way to redirect or access stderr output when launching a .app bundle via open,

Setting all other issues aside, any Unix process has control over it's own file handles in including stderr. I don't have a code snippet at hand, but the process involves using the "dup" and "dup2" syscalls to reroute the relevant file handles. The specific code would be exactly the same as basically "any" Unix system. I'm not sure if I'd actually do this, but if you want to, that's what's involved.

or any best practice for logging critical failures from a GUI app when terminal output isn't visible?

os_log is the systems "core" logging API and is where most logg output should already be routed. However, it's extremely powerful and highly customizable. Everything it's capable of is a topic in it's own right, but "Your Friend the System Log" is probably where I would start. One side comment here is that if you do choose to implement your own logging system, I would strongly recommend that you:

  1. Make sure your log messages are also logged through os_log to the system log.

  2. Make sure that your logging's timestamp format matches as closely as possible what the system logs.

That second point is actually really critical, as one of the most useful ways to debug a complex issue is to have an app level log which you can then correlate with the system log (generally through a sysdiagnose). The app log then services as an "index" into the system log (which shows you what's happening across the broader system). Of course, that process is much harder if the app time stamp isn't accurate enough and/or is formatted in a way that makes it hard to correlate with system log.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Hi @DTS Engineer @DTS Engineer ,

Thankyou for your response and efforts. Was missing the following in my open commands:: --stderr PATH Launches the application with stderr connected to PATH. and was looking for this.

My issue has been resolved. Thanks again.

How to capture stderr from a macOS GUI app (UIKit/AppKit) when launched via open or Finder?
 
 
Q