MacOS – Can’t load plist. Launchctl says “Invalid property list”, tried plutil, SIP, permissions

high sierralaunchdmacosplist

I want to use the following plist to run a backup script under macos High Sierra.

File name:
com.pollux.backup.plist

Content:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.pollux.backup.plist</string>
    <key>ProgramArguments</key>
    <array>
     <string>sh</string>
     <string>-c</string>
     <string>/bin/backup_pollux_server</string>
     <key>KeepAlive</key>
     </array>
     <key>RunAtLoad</key>
     <true/>
     <key>StartInterval</key>
     <integer>3600</integer>
     <key>StandardErrorPath</key>
     <string>/tmp/pollux_backup.err</string>
     <key>StandardOutPath</key>
     <string>/tmp/pollux_backup.out</string>
  </dict>
</plist>

Permissions: -rw-r--r--@ 1 root wheel 694 3 Apr 19:57 com.pollux.backup.plist

I use the same script and plist to backup my wife’s MacBook (Mavericks). It runs flawlessly. But when I try to load it with launchctl at my MacBook I get the following error message:

/Library/LaunchDaemons/com.pollux.backup.plist: Invalid property list

I checked the plist with plutil:

LaunchDaemons pollux$ plutil com.pollux.backup.plist
com.pollux.backup.plist: OK

xmllint just shows the content of the plist.

I switched off the SIP:

LaunchDaemons pollux$ csrutil status
System Integrity Protection status: disabled.

Does anyone have an idea what to try next?

Best Answer

The key KeepAlive had to be removed from the ProgramArguments array and properly enabled (<true/>).

This is how it works now:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.pollux.backup</string>
    <key>ProgramArguments</key>
    <array>
     <string>sh</string>
     <string>-c</string>
     <string>/bin/backup_pollux_server</string>
     </array>
     <key>RunAtLoad</key>
     <true/>
     <key>KeepAlive</key>
     <true/>
     <key>StartInterval</key>
     <integer>3600</integer>
     <key>StandardErrorPath</key>
     <string>/tmp/pollux_backup.err</string>
     <key>StandardOutPath</key>
     <string>/tmp/pollux_backup.out</string>
  </dict>
</plist>