grpc/grpc-go · error
authz: requires refresh interval
Error message
authz: requires refresh interval(%v) greater than 0s
What it means
Returned by authz.NewFileWatcherWithOptions (grpc_authz_server_interceptors.go:140) when FileWatcherOptions.RefreshDuration is <= 0. The interceptor spawns a background goroutine (run, line 153) that ticks on RefreshDuration via time.NewTicker to re-read the policy file; a zero or negative duration is an invalid ticker interval and is rejected before the goroutine starts.
Solutions
- Set a positive RefreshDuration, e.g. 10*time.Second or any interval appropriate to how often your policy file changes.
- If you do not want periodic reload, use authz.NewStatic (a one-shot static policy) rather than the file watcher.
- Validate the parsed interval before constructing the interceptor and fail fast with a clear message.
Example fix
// before
fw, err := authz.NewFileWatcher("/etc/grpc/policy.json", 0)
// after
fw, err := authz.NewFileWatcher("/etc/grpc/policy.json", 30*time.Second) Defensive patterns
Strategy: validation
Validate before calling
if refresh <= 0 {
refresh = 30 * time.Second // sane default
}
fw, err := authz.NewFileWatcher(policyPath, refresh) Try / catch
fw, err := authz.NewFileWatcher(policyPath, refresh)
if err != nil {
if strings.Contains(err.Error(), "refresh interval") {
// set a positive duration and reconstruct
}
} Prevention
- Always pass a positive RefreshDuration to the file watcher.
- Use NewStatic if you do not want periodic reload.
- Validate interval parsed from config before constructing the interceptor.
When it happens
Trigger: Calling NewFileWatcher(file, 0) or NewFileWatcherWithOptions with RefreshDuration unset (defaults to 0 because time.Duration zero value is 0); passing a negative duration; computing the interval from config that yielded 0.
Common situations: Forgetting to set RefreshDuration when using NewFileWatcherWithOptions; env-driven interval parsed as 0 on parse failure; tests that pass 0 for convenience.
Related errors
- "allow_rules" is not present
- "allow_rules
- authz: authorization policy file path is empty
- : "name" is not present
- %d: %v
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/5a2e57ff75c667dd.
Report an issue: GitHub.
Appendix: source
Thrown at authz/grpc_authz_server_interceptors.go:140
// 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 {
if err := i.updateInternalInterceptor(); err != nil {
logger.Warningf("authorization policy reload status err: %v", err)
}View on GitHub (pinned to 0c51461d27)