fatedier/frp · error

include: directory of %s not exist

Error message

include: directory of %s not exist

What it means

An includes[] entry points at a directory that does not exist on disk (os.Stat returns IsNotExist). frp validates include directories up front so a typo'd glob silently matching nothing can't hide configuration that the user believes is loaded.

Source

Thrown at pkg/config/v1/validation/client.go:186

	if !slices.Contains(SupportedTransportProtocols, c.Protocol) {
		errs = AppendError(errs, fmt.Errorf("invalid transport.protocol, optional values are %v", SupportedTransportProtocols))
	}
	if !slices.Contains(SupportedWireProtocols, c.WireProtocol) {
		errs = AppendError(errs, fmt.Errorf("invalid transport.wireProtocol, optional values are %v", SupportedWireProtocols))
	}
	return warnings, errs
}

func validateIncludeFiles(files []string) (Warning, error) {
	var errs error
	for _, f := range files {
		absDir, err := filepath.Abs(filepath.Dir(f))
		if err != nil {
			errs = AppendError(errs, fmt.Errorf("include: parse directory of %s failed: %v", f, err))
			continue
		}
		if _, err := os.Stat(absDir); os.IsNotExist(err) {
			errs = AppendError(errs, fmt.Errorf("include: directory of %s not exist", f))
		}
	}
	return nil, errs
}

func ValidateAllClientConfig(
	c *v1.ClientCommonConfig,
	proxyCfgs []v1.ProxyConfigurer,
	visitorCfgs []v1.VisitorConfigurer,
	unsafeFeatures *security.UnsafeFeatures,
) (Warning, error) {
	validator := NewConfigValidator(unsafeFeatures)
	var warnings Warning
	if c != nil {
		warning, err := validator.ValidateClientCommonConfig(c)
		warnings = AppendError(warnings, warning)
		if err != nil {
			return warnings, err

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. mkdir -p the directory named in the error message
  2. Fix the path in includes[] (absolute paths are safest for services)
  3. If includes are optional by design, guard by creating the directory in your deploy script/systemd ExecStartPre

Example fix

# before
includes = ["/etc/frpc/conf.d/*.toml"]  # dir absent
# shell:
# mkdir -p /etc/frpc/conf.d

# after
includes = ["/etc/frpc/conf.d/*.toml"]  # dir exists
Defensive patterns

Strategy: validation

Validate before calling

for _, inc := range cfg.Includes {
    dir := filepath.Dir(inc)
    if _, err := os.Stat(dir); os.IsNotExist(err) {
        // provision the directory or drop the include before starting frpc
    }
}

Prevention

When it happens

Trigger: includes = ["/etc/frpc/conf.d/*.toml"] when /etc/frpc/conf.d hasn't been created; deploying frpc to a new host without provisioning the include directory; wrong relative base (cwd-dependent paths).

Common situations: Packaging/deployment scripts that forget to create the conf.d directory; running frpc from a different directory than intended so relative includes resolve elsewhere; renaming directories without updating includes.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/bc916e860f2b1a11. Report an issue: GitHub.