Failed with result 'protocol'
Состояние protocol значит, что служба не выполнила то, чего требует её объявленный тип. Для Type=notify это отсутствие уведомления о готовности, для Type=dbus — не занятое имя на шине, для Type=forking — отсутствие ожидаемого дочернего процесса.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Type=notify, но уведомление не пришло, а процесс завершилсяsystemd ждёт READY=1 от программы. Если процесс завершился успешно, так и не отчитавшись, договор нарушен — это не таймаут, а именно нарушение протокола.
-
Type=dbus, а имя на шине не занятоПри этом типе служба считается запущенной, когда занимает имя из
BusName=. Если имя не то или служба не работает с шиной, договор не выполняется. -
Type=forking, но дочернего процесса нетsystemd ждёт, что исходный процесс завершится, оставив работающего потомка. Программа, не уходящая в фон, при этом типе нарушает договор.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Все параметры договора в одном выводе: обычно несоответствие видно сразу.
systemctl show myapp.service -p Type -p NotifyAccess -p BusName -p PIDFilesystemd поясняет, чего он ждал и не получил.
journalctl -xeu myapp.service --no-pager -n 30Решение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
Type=notify, но уведомление не пришло, а процесс завершился- Почему происходит
- systemd ждёт READY=1 от программы. Если процесс завершился успешно, так и не отчитавшись, договор нарушен — это не таймаут, а именно нарушение протокола.
- Как проверить
-
Посмотрите тип и поведение процесса.
systemctl show myapp.service -p Type -p NotifyAccess journalctl -u myapp.service -n 30 --no-pager
- Как исправить
-
Смените тип на
simpleилиexec, если программа не умеет отчитываться. Если умеет, проверьтеNotifyAccess=: при значенииmainуведомление от дочернего процесса не принимается.NotifyAccess=all
Type=dbus, а имя на шине не занято- Почему происходит
- При этом типе служба считается запущенной, когда занимает имя из
BusName=. Если имя не то или служба не работает с шиной, договор не выполняется.
- Как проверить
-
Посмотрите имя и проверьте его на шине.
systemctl show myapp.service -p Type -p BusName busctl list | grep -i myapp
- Как исправить
-
Исправьте
BusName=или смените тип, если служба к шине не обращается.
Type=forking, но дочернего процесса нет- Почему происходит
- systemd ждёт, что исходный процесс завершится, оставив работающего потомка. Программа, не уходящая в фон, при этом типе нарушает договор.
- Как проверить
-
Посмотрите тип и наличие флага демонизации.
systemctl show myapp.service -p Type -p PIDFile systemctl cat myapp.service | grep ExecStart
- Как исправить
-
Для программ, работающих на переднем плане, нужен
Type=simpleилиexec. Тип forking оставляйте только настоящим демонам и обязательно сPIDFile=.
Пример вывода
Тип notify у программы, которая просто отработала и вышла. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
× myapp.service - My application
Active: failed (Result: protocol) since Mon 2026-09-15 22:14:55 MSK; 1s ago
systemd[1]: myapp.service: Failed to start: Protocol error
systemd[1]: myapp.service: Failed with result 'protocol'.
Связанные ошибки
- Failed with result 'timeout' Состояние timeout: служба не уложилась в отведённое время при запуске, остановке или перезагрузке настроек.
- status=0/SUCCESS, но служба считается упавшей Программа завершилась успешно, а systemctl показывает inactive или failed. Разбор: Type=simple против forking, RemainAfterExit, демонизация.
- Job for … failed because a timeout was exceeded Задание на запуск прервано по таймауту. Как отличить медленный старт от заблокированного и правильно настроить TimeoutStartSec.
- Failed with result 'core-dump' Состояние core-dump: процесс службы аварийно завершился и сохранил дамп памяти. Как открыть дамп и прочитать трассировку.
- Failed with result 'exec-condition' и condition failed Состояния exec-condition и condition failed: запуск не состоялся, потому что условие не выполнено. Это не сбой, а задуманное поведение.
- Failed with result 'exit-code' Состояние exit-code: служба завершилась с ненулевым кодом. Что это сообщение значит и где искать настоящую причину.
- Failed with result 'oom-kill' Состояние oom-kill: процесс службы убит из-за нехватки памяти. Как понять, упёрлись в предел службы или в память машины.
- Failed with result 'resources' Состояние resources: systemd не смог выделить ресурсы для запуска службы. Чем отличается от кодов 200-й группы и что проверять.
Источники
-
systemd.service(5)
Значение protocol в таблице Result; Type=notify, dbus, forking и их требования. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено на Type=notify у программы без уведомления и на Type=dbus без BusName.