dapr/dapr · error
failed to start API gRPC server: %w
Error message
failed to start API gRPC server: %w
What it means
Returned when DaprRuntime.Run cannot start the public API gRPC server (startGRPCAPIServer). The underlying failure is almost always the net.Listen on the API gRPC port (default 50001) or, when --unix-domain-socket is set, creating the gRPC Unix domain socket file. The error wraps the OS-level cause; startup aborts.
Source
Thrown at pkg/runtime/runtime.go:821
if err = a.loadWorkflowAccessPolicies(ctx); err != nil {
return fmt.Errorf("failed to load workflow access policies: %w", err)
}
a.reloader.SetPolicyRecompiler(reconciler.WorkflowAccessPolicyOptions{
AppID: a.runtimeConfig.id,
Loader: a.reloader.Loader(),
CompStore: a.compStore,
Recompiler: a.workflowAccessPolicies.Store,
Healthz: a.runtimeConfig.healthz,
})
if err = a.runnerCloser.AddCloser(a.daprGRPCAPI); err != nil {
return err
}
err = a.startGRPCAPIServer(ctx, a.daprGRPCAPI, a.runtimeConfig.apiGRPCPort)
if err != nil {
return fmt.Errorf("failed to start API gRPC server: %w", err)
}
if a.runtimeConfig.unixDomainSocket != "" {
log.Info("API gRPC server is running on a Unix Domain Socket")
} else {
log.Infof("API gRPC server is running on port %v", a.runtimeConfig.apiGRPCPort)
}
// Start HTTP Server
err = a.startHTTPServer(ctx)
if err != nil {
return fmt.Errorf("failed to start HTTP server: %w", err)
}
if a.runtimeConfig.unixDomainSocket != "" {
log.Info("HTTP server is running on a Unix Domain Socket")
} else {
log.Infof("HTTP server is running on port %v", a.runtimeConfig.httpPort)View on GitHub (pinned to 74ad417027)
Solutions
- Inspect the wrapped error: 'address already in use' means a port conflict, 'permission denied' means privileged port or UDS dir perms
- Free the conflicting port (lsof -i :50001) or set a different one via --dapr-grpc-port
- If using --unix-domain-socket, ensure the directory exists, is writable by the daprd user, and is on a filesystem that supports UDS (not NFS/overlay quirks)
- Ensure only one daprd runs per app-id/port pair
Example fix
# before daprd --app-id myapp --dapr-grpc-port 50001 # after (port 50001 taken by another process) daprd --app-id myapp --dapr-grpc-port 50101
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: is the API gRPC port bindable?
func checkPortFree(port int) error {
ln, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", port))
if err != nil { return fmt.Errorf("gRPC API port %d unavailable: %w", port, err) }
ln.Close()
return nil
} Type guard
func isAddrInUse(err error) bool {
var opErr *net.OpError
if errors.As(err, &opErr) {
return errors.Is(opErr.Err, syscall.EADDRINUSE)
}
return false
} Prevention
- Assign one distinct port triple (http, grpc, internal-grpc) per sidecar on shared hosts
- When embedding the runtime, probe the ports with net.Listen before constructing DaprRuntime
- For UDS deployments, mount an emptyDir at the socket dir and verify write access in an initContainer
When it happens
Trigger: Another process already bound the API gRPC port; --dapr-grpc-port set to a privileged port (<1024) while running unprivileged; Unix domain socket directory missing, read-only, or lacking write permission; port already taken by a second daprd instance for the same app-id.
Common situations: Two sidecars (or a leftover daprd) on the same host using default port 50001; container with a read-only volume mounted as the UDS dir; SELinux/AppArmor denying socket creation; Docker port-map collision.
Related errors
- failed to start internal gRPC server: %w
- could not listen on port %d: %w
- failed to start HTTP server: %w
- could not listen on port %d: %w
- failed to listen on %s: %w
AI-assisted analysis of dapr/dapr@74ad417027 (2026-08-16).
Data as JSON: /api/errors/b705591b95dc9eab.
Report an issue: GitHub.