AlexxIT/go2rtc · error
exec: bin not in allow_paths:
Error message
exec: bin not in allow_paths:
What it means
The exec stream source launches external binaries; for safety, if allow_paths is configured, only whitelisted executables may be started. This error means the binary that exec is about to spawn (cmd.Args[0]) is not in that whitelist, so the handler aborts and closes the command.
Solutions
- Add the exact executable path/name from the exec: URL to allow_paths
- Match formats: if the exec URL uses a bare name, allow the name; if absolute, allow the absolute path
- If the binary moved, update either the stream URL or the allowlist entry
- Remove allow_paths if per-binary restriction is not needed (not recommended)
Example fix
// before allow_paths: ["/usr/bin/ffmpeg"] streams: cam: exec:/usr/local/bin/ffmpeg ... // after allow_paths: ["/usr/bin/ffmpeg", "/usr/local/bin/ffmpeg"]
Defensive patterns
Strategy: validation
Validate before calling
if allowPaths != nil && !slices.Contains(allowPaths, bin) { return fmt.Errorf("add %q to allow_paths", bin) } Try / catch
_, err := streams.Get(url); if err != nil && strings.Contains(err.Error(), "allow_paths") { /* resolve binary path and extend allowlist */ } Prevention
- Generate allow_paths from the same list of binaries used in exec: sources
- After system upgrades, verify binary paths referenced by exec sources still exist
- Use absolute paths consistently in both URLs and allowlist
When it happens
Trigger: A stream source exec:BIN ... where allow_paths is non-nil and does not exactly contain BIN (cmd.Args[0]). Includes cases where the URL's binary resolves differently (bare name vs absolute path) than the allowlist entry.
Common situations: After adding allow_paths to the config for the echo module, exec sources break because they use different binaries; binary path changed after a system update; typo in the exec URL; allowlist uses relative name while exec URL uses absolute path.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- echo: bin not in allow_paths:
- exec: rtsp module disabled
- config file disabled
- exec: timeout
- expr: result is empty
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/0c33bd7b8a9aa56b.
Report an issue: GitHub.
Appendix: source
Thrown at internal/exec/exec.go:92
if i := strings.Index(rawURL, "{output}"); i > 0 {
if rtsp.Port == "" {
return nil, errors.New("exec: rtsp module disabled")
}
sum := md5.Sum([]byte(rawURL))
path = "/" + hex.EncodeToString(sum[:])
rawURL = rawURL[:i] + "rtsp://127.0.0.1:" + rtsp.Port + path + rawURL[i+8:]
}
cmd := shell.NewCommand(rawURL[5:]) // remove `exec:`
cmd.Stderr = &logWriter{
buf: make([]byte, 512),
debug: log.Debug().Enabled(),
}
if allowPaths != nil && !slices.Contains(allowPaths, cmd.Args[0]) {
_ = cmd.Close()
return nil, errors.New("exec: bin not in allow_paths: " + cmd.Args[0])
}
if s := query.Get("killsignal"); s != "" {
sig := syscall.Signal(core.Atoi(s))
cmd.Cancel = func() error {
log.Debug().Msgf("[exec] kill with signal=%d", sig)
return cmd.Process.Signal(sig)
}
}
if s := query.Get("killtimeout"); s != "" {
cmd.WaitDelay = time.Duration(core.Atoi(s)) * time.Second
}
if query.Get("backchannel") == "1" {
return pcm.NewBackchannel(cmd, query.Get("audio"))
}
View on GitHub (pinned to c245815e75)