grpc/grpc-go · error
invalid (non-empty) authority: %v
Error message
invalid (non-empty) authority: %v
What it means
Thrown by the gRPC unix socket resolver's Build method when the dial target URL contains a non-empty host (authority) component. The 'unix' and 'unix-abstract' schemes require the socket path to live entirely in the URL path/opaque portion, so any authority (e.g. a hostname between 'unix://' and the path) is rejected. It is a hard failure: the resolver returns the error and no connection is attempted.
Source
Thrown at internal/resolver/unix/unix.go:38
package unix
import (
"fmt"
"google.golang.org/grpc/internal/transport/networktype"
"google.golang.org/grpc/resolver"
)
const unixScheme = "unix"
const unixAbstractScheme = "unix-abstract"
type builder struct {
scheme string
}
func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) {
if target.URL.Host != "" {
return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.URL.Host)
}
// gRPC was parsing the dial target manually before PR #4817, and we
// switched to using url.Parse() in that PR. To avoid breaking existing
// resolver implementations we ended up stripping the leading "/" from the
// endpoint. This obviously does not work for the "unix" scheme. Hence we
// end up using the parsed URL instead.
endpoint := target.URL.Path
if endpoint == "" {
endpoint = target.URL.Opaque
}
addr := resolver.Address{Addr: endpoint}
if b.scheme == unixAbstractScheme {
// We can not prepend \0 as c++ gRPC does, as in Golang '@' is used to signify we do
// not want trailing \0 in address.
addr.Addr = "@" + addr.Addr
}
cc.UpdateState(resolver.State{Addresses: []resolver.Address{networktype.Set(addr, "unix")}})View on GitHub (pinned to 03255a9237)
Solutions
- Drop the authority: dial "unix:///tmp/foo.sock" (note the triple slash, leaving Host empty) or "unix:/tmp/foo.sock".
- If building the target dynamically, prepend only when the path lacks a scheme and never interpolate a hostname: grpc.Dial(fmt.Sprintf("unix:%s", sockPath), ...).
- For abstract namespace sockets on Linux use the 'unix-abstract:' scheme with just the name, e.g. "unix-abstract:myname".
- If you genuinely need to override authority, note OverrideAuthority forces 'localhost' anyway, so there is no supported way to keep a custom authority with the unix scheme.
Example fix
// before
conn, err := grpc.Dial("unix://localhost/run/docker.sock", grpc.WithInsecure())
// after
conn, err := grpc.Dial("unix:///run/docker.sock", grpc.WithInsecure()) Defensive patterns
Strategy: validation
Validate before calling
func validUnixTarget(t string) error {
u, err := url.Parse(t)
if err != nil { return err }
if u.Scheme != "unix" && u.Scheme != "unix-abstract" { return fmt.Errorf("unexpected scheme %q", u.Scheme) }
if u.Host != "" { return fmt.Errorf("unix target must have empty authority; got %q", u.Host) }
return nil
}
// before dialing:
if err := validUnixTarget(target); err != nil { return err } Type guard
func isUnixTarget(t string) bool {
u, err := url.Parse(t)
return err == nil && (u.Scheme == "unix" || u.Scheme == "unix-abstract") && u.Host == ""
} Prevention
- Always build unix dial targets with a helper that guarantees triple-slash form for the unix scheme.
- Never interpolate a hostname into a unix:// URL; the unix resolver overrides authority to localhost anyway.
- Lint dial target strings in CI to reject unix://<non-empty-host>.
When it happens
Trigger: Dialing a target like "unix://localhost/tmp/foo.sock" or "unix://somehost/run/docker.sock" — anything where the URL parses a Host field. The check is the single guard `if target.URL.Host != ""` in unix.go:37, so even an authority that happens to be a valid hostname trips it.
Common situations: Developers copy a unix socket path from a Docker/containerd config that already embeds a host, or assemble the target via fmt.Sprintf("unix://%s", path) which yields three slashes only when path starts with '/'. Confusion between the gRPC-native 'unix:' scheme and a URL that looks RFC-conformant.
Related errors
- delegating_resolver: failed to determine proxy URL for targe
- dns resolver: missing address
- dns resolver: missing port after port-separator colon
- passthrough: received empty target in Build()
- endpoints list is empty
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/b0fb6155cedd890a.
Report an issue: GitHub.