fatedier/frp · error
failed to execute command %v: %v
Error message
failed to execute command %v: %v
What it means
ExecSource.Resolve() wraps the exec.Cmd.Output() failure for the configured command. The wrapped error is usually an *exec.ExitError (non-zero exit or signal kill), a "command not found" path error, or a context-deadline error if ctx was cancelled. Only stdout is captured; anything the command writes to stderr is discarded by Output().
Source
Thrown at pkg/config/v1/value_source.go:153
}
// Resolve reads and returns the content captured from stdout of launched subprocess.
func (e *ExecSource) Resolve(ctx context.Context) (string, error) {
if err := e.Validate(); err != nil {
return "", err
}
cmd := exec.CommandContext(ctx, e.Command, e.Args...)
if len(e.Env) != 0 {
cmd.Env = os.Environ()
for _, env := range e.Env {
cmd.Env = append(cmd.Env, env.Name+"="+env.Value)
}
}
content, err := cmd.Output()
if err != nil {
return "", fmt.Errorf("failed to execute command %v: %v", e.Command, err)
}
// Trim whitespace, which is important for exec-based tokens
return strings.TrimSpace(string(content)), nil
}
View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Run the exact command manually as the frp service user to see the real failure: sudo -u frp <command> <args...>.
- Ensure the binary/script exists in the container/image and PATH; use an absolute path for command.
- If the command is slow, pass a context with a longer deadline to Resolve().
- Check exit status in the returned error (*exec.ExitError) — stderr output is not included in this error message.
- For scripts, verify the executable bit and shebang.
Example fix
# before [auth.token.valueSource] type = "exec" exec.command = "get-token" # not in PATH inside container # after exec.command = "/usr/local/bin/get-token" # or inline shell: exec.command = "sh" exec.args = ["-c", "cat /run/secrets/token"]
Defensive patterns
Strategy: try-catch
Validate before calling
func execResolves(command string, args []string) error {
if command == "" {
return errors.New("empty command")
}
path, err := exec.LookPath(command)
if err != nil {
return fmt.Errorf("command %q not found in PATH: %w", command, err)
}
_ = path
return nil
} Try / catch
val, err := vs.Resolve(ctx)
if err != nil {
var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
// command ran but failed: capture stderr yourself by running it out-of-band; fix credentials/env
log.Printf("helper exited %d", exitErr.ExitCode())
} else if ctx.Err() != nil {
// deadline: lengthen the context timeout
}
return err
} Prevention
- Test the helper command manually as the frp service user before enabling it.
- Prefer absolute paths for command; ensure the binary ships in the container image.
- Give Resolve a context deadline sized for the helper (cloud IAM calls can take seconds).
- Remember stderr is discarded — make the helper report failures via exit code.
When it happens
Trigger: ValueSource{Type: "exec"}.Resolve(ctx) where the command exits non-zero, does not exist in PATH, is not executable, is killed by the context deadline, or cannot run due to missing runtime (e.g. no shell, missing interpreter).
Common situations: Token-fetch helper (aws sts get-session-token, vault print token) fails because of expired credentials or no network; command installed on the admin's laptop but not in the frpc container image; context deadline too short for a cloud API call; script not marked executable or uses a shebang for a missing interpreter.
Related errors
- exec command cannot be empty
- exec env name cannot be empty
- exec env name cannot contain '='
- exec configuration is required when type is 'exec'
- file path cannot be empty
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/7bb2403ef96ca7fc.
Report an issue: GitHub.