grpc/grpc-go · error
authz: authorization policy file path is empty
Error message
authz: authorization policy file path is empty
What it means
Returned by authz.NewFileWatcherWithOptions (grpc_authz_server_interceptors.go:137) when FileWatcherOptions.PolicyFile is the empty string. The file-based authorization interceptor needs a policy file to read and watch, so an empty path is rejected up front rather than failing later.
Source
Thrown at authz/grpc_authz_server_interceptors.go:137
}
// NewFileWatcher returns a new FileWatcherInterceptor from a policy file
// that contains JSON string of authorization policy and a refresh duration to
// specify the amount of time between policy refreshes.
func NewFileWatcher(file string, duration time.Duration) (*FileWatcherInterceptor, error) {
return NewFileWatcherWithOptions(FileWatcherOptions{PolicyFile: file, RefreshDuration: duration, OnPolicyUpdate: nil})
}
// NewFileWatcherWithOptions returns a new FileWatcherInterceptor from a set of
// options.
//
// # Experimental
//
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
// later release.
func NewFileWatcherWithOptions(options FileWatcherOptions) (*FileWatcherInterceptor, error) {
if options.PolicyFile == "" {
return nil, fmt.Errorf("authz: authorization policy file path is empty")
}
if options.RefreshDuration <= time.Duration(0) {
return nil, fmt.Errorf("authz: requires refresh interval(%v) greater than 0s", options.RefreshDuration)
}
i := &FileWatcherInterceptor{options: options}
if err := i.updateInternalInterceptor(); err != nil {
return nil, err
}
ctx, cancel := context.WithCancel(context.Background())
i.cancel = cancel
// Create a background go routine for policy refresh.
go i.run(ctx)
return i, nil
}
func (i *FileWatcherInterceptor) run(ctx context.Context) {
ticker := time.NewTicker(i.options.RefreshDuration)
for {View on GitHub (pinned to 03255a9237)
Solutions
- Provide a non-empty policy file path to NewFileWatcher / NewFileWatcherWithOptions.
- Read the path from an env var or flag and fail fast at startup if it is empty.
- If authz is optional, skip constructing the interceptor entirely when no path is configured instead of passing "".
- Validate the path exists before passing it (also avoids the later read-failed error).
Example fix
// before
az, err := authz.NewFileWatcher("", 10*time.Second)
// after
path := os.Getenv("GRPC_AUTHZ_POLICY")
if path == "" {
log.Fatal("GRPC_AUTHZ_POLICY must be set")
}
az, err := authz.NewFileWatcher(path, 10*time.Second) Defensive patterns
Strategy: validation
Validate before calling
if strings.TrimSpace(options.PolicyFile) == "" {
return fmt.Errorf("authz policy file path is required")
} Try / catch
az, err := authz.NewFileWatcherWithOptions(opts)
if err != nil {
if strings.Contains(err.Error(), "policy file path is empty") {
log.Fatal("set --authz-policy")
}
} Prevention
- Wire the policy path from an explicit flag/env var and fail fast if unset.
- Skip authz setup when policy is optional instead of passing an empty string.
- Add a startup config check listing required fields.
When it happens
Trigger: Calling NewFileWatcher("", duration) or NewFileWatcherWithOptions with an unset PolicyFile, e.g. when the path is supposed to come from an env var or config flag that was not provided.
Common situations: Forgetting to wire a --authz-policy flag; env var not set in the deployment; config struct field left as the zero value; conditional that should set the file but did not run.
Related errors
- authz: requires refresh interval(%v) greater than 0s
- policyFile(%s) read failed: %v
- missing server_listener_resource_name_template in the bootst
- "headers" %d: "key" is not present
- "headers" %d: unsupported "key" %s
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/d2c730139f8e9227.
Report an issue: GitHub.