{"record":{"id":"5a2e57ff75c667dd","repo":"grpc/grpc-go","slug":"authz-requires-refresh-interval-v-greater-than","errorCode":null,"errorMessage":"authz: requires refresh interval(%v) greater than 0s","messagePattern":"authz: requires refresh interval\\((.+?)\\) greater than 0s","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"authz/grpc_authz_server_interceptors.go","lineNumber":140,"sourceCode":"// that contains JSON string of authorization policy and a refresh duration to\n// specify the amount of time between policy refreshes.\nfunc NewFileWatcher(file string, duration time.Duration) (*FileWatcherInterceptor, error) {\n\treturn NewFileWatcherWithOptions(FileWatcherOptions{PolicyFile: file, RefreshDuration: duration, OnPolicyUpdate: nil})\n}\n\n// NewFileWatcherWithOptions returns a new FileWatcherInterceptor from a set of\n// options.\n//\n// # Experimental\n//\n// Notice: This API is EXPERIMENTAL and may be changed or removed in a\n// later release.\nfunc NewFileWatcherWithOptions(options FileWatcherOptions) (*FileWatcherInterceptor, error) {\n\tif options.PolicyFile == \"\" {\n\t\treturn nil, fmt.Errorf(\"authz: authorization policy file path is empty\")\n\t}\n\tif options.RefreshDuration <= time.Duration(0) {\n\t\treturn nil, fmt.Errorf(\"authz: requires refresh interval(%v) greater than 0s\", options.RefreshDuration)\n\t}\n\ti := &FileWatcherInterceptor{options: options}\n\tif err := i.updateInternalInterceptor(); err != nil {\n\t\treturn nil, err\n\t}\n\tctx, cancel := context.WithCancel(context.Background())\n\ti.cancel = cancel\n\t// Create a background go routine for policy refresh.\n\tgo i.run(ctx)\n\treturn i, nil\n}\n\nfunc (i *FileWatcherInterceptor) run(ctx context.Context) {\n\tticker := time.NewTicker(i.options.RefreshDuration)\n\tfor {\n\t\tif err := i.updateInternalInterceptor(); err != nil {\n\t\t\tlogger.Warningf(\"authorization policy reload status err: %v\", err)\n\t\t}","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/authz/grpc_authz_server_interceptors.go#L122-L158","documentation":"Returned by authz.NewFileWatcherWithOptions (grpc_authz_server_interceptors.go:140) when RefreshDuration is <= 0. The file watcher uses time.NewTicker with this duration to periodically reload the policy; a zero or negative duration would panic the ticker, so the constructor rejects it.","triggerScenarios":"Calling NewFileWatcher(file, 0), NewFileWatcher(file, -time.Second), or NewFileWatcherWithOptions with an uninitialized RefreshDuration (the zero value time.Duration(0)).","commonSituations":"FileWatcherOptions struct constructed without setting RefreshDuration; a config that conditionally sets the duration but leaves it zero when the condition is false; passing time.Duration from a parsed value that defaulted to 0.","solutions":["Set RefreshDuration to a positive value such as 10*time.Second or 1*time.Minute.","Default the duration to a sane positive value when it is unset in config.","Validate duration > 0 before calling the constructor and surface a clear config error.","If you do not want periodic reload, use authz.NewStatic (one-shot) instead of the file watcher."],"exampleFix":"// before\naz, err := authz.NewFileWatcherWithOptions(\n    authz.FileWatcherOptions{PolicyFile: path}) // RefreshDuration == 0\n\n// after\ndur := cfg.RefreshDuration\nif dur <= 0 {\n    dur = 30 * time.Second\n}\naz, err := authz.NewFileWatcherWithOptions(\n    authz.FileWatcherOptions{PolicyFile: path, RefreshDuration: dur})","handlingStrategy":"validation","validationCode":"if options.RefreshDuration <= 0 {\n    options.RefreshDuration = 30 * time.Second\n}","typeGuard":null,"tryCatchPattern":"if _, err := authz.NewFileWatcherWithOptions(opts); err != nil {\n    if strings.Contains(err.Error(), \"refresh interval\") {\n        opts.RefreshDuration = 30 * time.Second\n    }\n}","preventionTips":["Default RefreshDuration to a positive value at the config layer.","Use authz.NewStatic when periodic reload is not needed.","Always populate the whole FileWatcherOptions struct."],"tags":["go","grpc","authz","config","time"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}