grpc/grpc-go · error

policyFile(%s) read failed: %v

Error message

policyFile(%s) read failed: %v

What it means

Returned by FileWatcherInterceptor.updateInternalInterceptor (grpc_authz_server_interceptors.go:175) when os.ReadFile fails on the policy file. It wraps the underlying OS error (e.g. not exist, permission denied). On initial construction this error propagates out of NewFileWatcherWithOptions; on later refresh ticks it is only logged as a warning and the last good policy is kept.

Source

Thrown at authz/grpc_authz_server_interceptors.go:175

			logger.Warningf("authorization policy reload status err: %v", err)
		}
		select {
		case <-ctx.Done():
			ticker.Stop()
			return
		case <-ticker.C:
		}
	}
}

// updateInternalInterceptor checks if the policy file that is watching has changed,
// and if so, updates the internalInterceptor with the policy. Unlike the
// constructor, if there is an error in reading the file or parsing the policy, the
// previous internalInterceptors will not be replaced.
func (i *FileWatcherInterceptor) updateInternalInterceptor() error {
	policyContents, err := os.ReadFile(i.options.PolicyFile)
	if err != nil {
		return fmt.Errorf("policyFile(%s) read failed: %v", i.options.PolicyFile, err)
	}
	if bytes.Equal(i.policyContents, policyContents) {
		return nil
	}
	i.policyContents = policyContents
	policyContentsString := string(policyContents)
	interceptor, err := NewStatic(policyContentsString)
	if err != nil {
		return err
	}
	atomic.StorePointer(&i.internalInterceptor, unsafe.Pointer(interceptor))
	logger.Infof("authorization policy reload status: successfully loaded new policy %v", policyContentsString)
	if i.options.OnPolicyUpdate != nil {
		i.options.OnPolicyUpdate(policyContentsString)
	}
	return nil
}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Verify the path is correct and the file is readable by the process user before constructing the watcher.
  2. In Kubernetes, ensure the ConfigMap/Secret volume is mounted and use startup ordering/readiness to delay boot until present.
  3. Fix filesystem permissions (chmod/chown) so the process can read the file.
  4. If the file may be briefly absent, pre-create it or retry construction rather than crashing.

Example fix

// before
az, err := authz.NewFileWatcher("/etc/authz/policy.json", 10*time.Second)
// error: policyFile(/etc/authz/policy.json) read failed: open ...: no such file

// after - verify existence first
path := "/etc/authz/policy.json"
if _, err := os.Stat(path); err != nil {
    log.Fatalf("authz policy not accessible: %v", err)
}
az, err := authz.NewFileWatcher(path, 10*time.Second)
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(options.PolicyFile); err != nil {
    return fmt.Errorf("authz policy file not readable: %w", err)
}

Try / catch

az, err := authz.NewFileWatcherWithOptions(opts)
if err != nil && strings.Contains(err.Error(), "read failed") {
    // retry after a short delay or fail with actionable message
    return fmt.Errorf("policy file unreadable: %w", err)
}

Prevention

When it happens

Trigger: The policy file path does not exist, is unreadable due to permissions, or the process lacks access at read time; a mounted volume/configmap is not yet attached when the server boots.

Common situations: Typo in the path; Kubernetes ConfigMap/Secret not mounted yet at startup; file owned by another user with no read bit; container filesystem mount misconfigured; file rotated/deleted under a running watcher.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/bd711cd84488ac5d. Report an issue: GitHub.