Skip to content

whisper backend run.sh forwards LocalAI's positional listen address, but main.go only parses -addr flag — backend always binds :50051 #11623

Description

@kamilsa

Summary

metal-whisper's (and presumably cpu-whisper/other whisper variants') run.sh forwards LocalAI's positional listen-address argument straight through to the whisper binary (exec "$CURDIR"/whisper "$@"), but backend/go/whisper/main.go parses its address exclusively via the Go flag package:

var addr = flag.String("addr", "localhost:50051", "the address to connect to")
...
flag.Parse()
if err := grpc.StartServer(*addr, &Whisper{}); err != nil { ... }

flag.Parse() does not treat a bare positional token like 127.0.0.1:63508 as a value for -addr; it's silently ignored (not even an error, since there are no required positional args). The binary therefore always binds the default localhost:50051, regardless of what port LocalAI actually assigned it and is trying to connect to.

The result: LocalAI's gRPC client connects to the port it allocated (e.g. 127.0.0.1:63508), finds nothing listening there, and reports a generic, misleading failure:

Backend process exited unexpectedly id="whisper-large-turbo" address="127.0.0.1:63508" process="run.sh" exitCode="2"
Failed to load model ... error=... rpc error: code = Unavailable desc = error reading from server: EOF

(The exitCode=2 here is actually from a later, unrelated failure once the loader gives up and kills the process it can't reach — the whisper process itself, bound to :50051, is running fine at that point; LocalAI just can't see it.)

Environment

  • LocalAI v4.8.2 (5ff25d9d145e0a03a5b9a3559c620f1e1204ca6d)
  • Backend metal-whisper (quay.io/go-skynet/local-ai-backends:latest-metal-darwin-arm64-whisper, digest sha256:4f18b4b228d2a750e74cf9f006e3789bb3d99da5b9d651e4fc1d8e55121346fa)
  • Also reproduced identically on metal-whisper-development (:master-metal-darwin-arm64-whisper), so this is not tied to one release
  • macOS 26.5.2, Apple M4 Pro (though the bug is platform-independent — it's a pure CLI-arg-parsing mismatch)

Reproduction

cd ~/backends/metal-whisper
./run.sh 127.0.0.1:59999
# ...
# 2026/08/20 15:15:54 gRPC Server listening at 127.0.0.1:50051   <-- wrong, ignored the arg entirely

# Whereas passing it as the flag the binary actually expects works correctly:
DYLD_LIBRARY_PATH="$(pwd)/lib" WHISPER_LIBRARY="$(pwd)/libgowhisper-fallback.so" \
  ./whisper -addr=127.0.0.1:59999
# 2026/08/20 15:17:25 gRPC Server listening at 127.0.0.1:59999   <-- correct

Root cause

backend/go/whisper/run.sh (all variants: metal-whisper, cpu-whisper, metal-whisper-development, etc., since they all share this generated launcher) does:

exec "$CURDIR"/whisper "$@"

but should be translating the positional address into the flag the Go binary's main.go expects, e.g.:

if [ -n "$1" ] && [[ "$1" != -* ]]; then
    set -- "-addr=$1" "${@:2}"
fi
exec "$CURDIR"/whisper "$@"

(This is the local patch I applied to work around it, confirmed working — the backend now listens on the port LocalAI actually assigned.)

Alternatively/better: fix it on the Go side so main.go accepts the address as os.Args[1] (a positional arg) the same way most of LocalAI's other backend main.gos presumably do, for consistency with however core actually invokes backends — whichever convention is the intended contract between LocalAI core and backend launchers, the two currently disagree, and it's the whisper backend that's out of step. Worth checking whether other backend main.gos in backend/go/* use positional os.Args vs flag.String("addr", ...), since a project-wide inconsistency here would explain why this slipped through.

Impact

Every model load through metal-whisper/cpu-whisper fails on any host where the assigned port isn't already 50051 for another reason — i.e. essentially always, since LocalAI dynamically allocates a fresh port per backend instance. This appears to make the whisper backend entirely non-functional out of the box.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions