fatedier/frp · error · ErrInvalidArgument
invalid argument: body can't be empty
Error message
invalid argument: body can't be empty
What it means
Returned by WriteConfigFile (PUT /api/config on the frpc admin API) when the request body is empty. frpc refuses zero-length writes so an empty body cannot truncate and destroy the live config file. It is a pure request-construction error on the caller side.
Source
Thrown at client/config_manager.go:70
log.Infof("success reload conf")
return nil
}
func (m *serviceConfigManager) ReadConfigFile() (string, error) {
if m.svr.configFilePath == "" {
return "", fmt.Errorf("%w: frpc has no config file path", configmgmt.ErrInvalidArgument)
}
content, err := os.ReadFile(m.svr.configFilePath)
if err != nil {
return "", fmt.Errorf("%w: %v", configmgmt.ErrInvalidArgument, err)
}
return string(content), nil
}
func (m *serviceConfigManager) WriteConfigFile(content []byte) error {
if len(content) == 0 {
return fmt.Errorf("%w: body can't be empty", configmgmt.ErrInvalidArgument)
}
if err := os.WriteFile(m.svr.configFilePath, content, 0o600); err != nil {
return err
}
return nil
}
func (m *serviceConfigManager) GetProxyStatus() []*proxy.WorkingStatus {
return m.svr.getAllProxyStatus()
}
func (m *serviceConfigManager) GetProxyConfig(name string) (v1.ProxyConfigurer, bool) {
// Try running proxy manager first
ws, ok := m.svr.getProxyStatus(name)
if ok {
return ws.Cfg, true
}View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Send the complete config file content as the PUT body: curl -X PUT --data-binary @frpc.toml http://127.0.0.1:7400/api/config.
- If your tooling produced an empty body, fix the template/render step so it emits at least a minimal valid config.
- Verify body length before sending (e.g. test -s frpc.toml) in scripts.
Example fix
# before curl -X PUT http://127.0.0.1:7400/api/config # 400 body can't be empty # after curl -X PUT --data-binary @frpc.toml http://127.0.0.1:7400/api/config
Defensive patterns
Strategy: validation
Validate before calling
// Never send an empty body to PUT /api/config.
if len(content) == 0 {
return errors.New("refusing to PUT empty config")
}
req, _ := http.NewRequest(http.MethodPut, base+"/api/config", bytes.NewReader(content)) Prevention
- Always PUT with --data-binary @file and test -s the file first
- Treat empty rendered templates as a hard error in config pipelines
When it happens
Trigger: PUT /api/config with an empty body, a body of only whitespace is fine but zero bytes is not; curl invoked without -d/--data-binary so no body is sent; a CI job whose config template rendered to an empty string.
Common situations: Automation that renders a TOML template and PUTs it while the template variables are all empty, yielding a zero-byte payload; curl commands missing --data-binary @file; HTTP clients that drop the body on redirects.
Related errors
- invalid argument: frpc has no config file path
- HTTP ${response.status}
- subdomain and custom domains should not be both empty
- invalid argument: %v
- apply config failed: %v
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/4aeec7e21f917c7b.
Report an issue: GitHub.