Unable to start VM with hookscript Proxmox? It’s almost always one of three things: the script isn’t executable, it exits non-zero, or it’s not where qm looks for it. The error message won’t tell you which, so trace it yourself.

Where Proxmox stores hookscripts
Hookscripts live in a snippets storage. By default that’s local, which maps to /var/lib/vz/snippets/ on the node. If you put the script anywhere else, qm won’t find it — you’ll get a generic ‘unable to start’ error with no hint about the path.
Check where yours is:
pvesm status
ls -l /var/lib/vz/snippets/
If the script isn’t in that directory, move it there. Then make sure the VM config points to the right storage and filename. The config line looks like hookscript: local:snippets/my-hook.sh. If you see hookscript: my-hook.sh without the storage prefix, that’s wrong.
Executable bit and shebang
The script needs the executable bit set, or Proxmox won’t run it. This is the ‘chmod +x’ advice everyone gives, and it’s right — but it’s not the only failure.
chmod +x /var/lib/vz/snippets/my-hook.sh
Also check the shebang. If the first line is missing or wrong, the script fails before it does anything. Use #!/bin/bash or whatever interpreter you need.

Phases and exit codes
Proxmox calls the hookscript with two arguments: the VMID and the phase. Phases include pre-start, post-start, pre-stop, post-stop. If the script exits non-zero during pre-start, the VM won’t start. That’s by design — the hook is meant to abort startup if something’s wrong.
But a lot of scripts exit non-zero accidentally. Maybe a command fails because it’s not installed, or a variable is empty. Test the script manually with the same arguments qm would pass:
/var/lib/vz/snippets/my-hook.sh 100 pre-start
echo $?
If $? isn’t 0, that’s your problem. Fix the script so it returns 0 on success.
Logs that actually help
The VM start task log in the Proxmox UI sometimes shows the hookscript error, but not always. Check the syslog:
journalctl -u pve-guests -f
Or run qm start from the command line to see the error directly:
qm start 100
That usually prints the hookscript’s stderr, which is more than the UI gives you.
My take
If you’re writing a hookscript, keep it dead simple. One thing it does, no fancy error handling, always exit 0 unless you really want to block startup. And test it manually before you attach it to a VM. Saves you from wondering why the VM won’t boot.
Related: Proxmox VM Fingerprint: What the Guest Can See and Which Identifiers You Can Change.