cloudflare/cloudflared · error
error writing %s: %v
Error message
error writing %s: %v
What it means
This error is returned by ServiceTemplate.Generate when os.WriteFile fails to write the rendered template buffer to the resolved path (e.g. the launchd plist file). The directory was created successfully, but the final file write failed — typically due to permissions, disk-full, or the destination being a directory. The message includes the resolved file path.
Source
Thrown at cmd/cloudflared/service_template.go:66
var buffer bytes.Buffer
err = tmpl.Execute(&buffer, args)
if err != nil {
return fmt.Errorf("error generating %s: %v", st.Path, err)
}
fileMode := os.FileMode(0o644)
if st.FileMode != 0 {
fileMode = st.FileMode
}
plistFolder := filepath.Dir(resolvedPath)
err = os.MkdirAll(plistFolder, 0o755)
if err != nil {
return fmt.Errorf("error creating %s: %v", plistFolder, err)
}
err = os.WriteFile(resolvedPath, buffer.Bytes(), fileMode)
if err != nil {
return fmt.Errorf("error writing %s: %v", resolvedPath, err)
}
return nil
}
func (st *ServiceTemplate) Remove() error {
resolvedPath, err := st.ResolvePath()
if err != nil {
return err
}
err = os.Remove(resolvedPath)
if err != nil {
return fmt.Errorf("error deleting %s: %v", resolvedPath, err)
}
return nil
}
func serviceAlreadyExistsWarn(service string) string {
return fmt.Sprintf("cloudflared service is already installed at %s; if you are running a cloudflared tunnel, you "+View on GitHub (pinned to 2253eeeb25)
Solutions
- Re-run the install with sudo so the plist is writable
- Check the destination path is not an existing directory or immutable file and remove/fix it if stale: ls -laO /Library/LaunchDaemons/com.cloudflare.cloudflared.plist
- Verify free disk space (df -h) and writable system volume
- Check MDM/endpoint-security software isn't blocking writes to LaunchDaemons
Example fix
// before $ cloudflared service install // open /Library/LaunchDaemons/...: permission denied // after $ sudo cloudflared service install
Defensive patterns
Strategy: try-catch
Validate before calling
if fi, err := os.Stat(resolvedPath); err == nil && fi.IsDir() {
return fmt.Errorf("%s exists as a directory; remove it before installing", resolvedPath)
}
if err := unix.Access(filepath.Dir(resolvedPath), unix.W_OK); err != nil {
return errors.New("insufficient permission to write service file; run with sudo")
} Type guard
func canWriteFile(path string) bool {
dir := filepath.Dir(path)
f, err := os.CreateTemp(dir, ".probe")
if err != nil { return false }
n := f.Name()
_ = f.Close()
_ = os.Remove(n)
return true
} Try / catch
if err := st.Generate(args); err != nil {
if strings.Contains(err.Error(), "error writing") {
if strings.Contains(err.Error(), "permission denied") {
// re-run with sudo
} else if strings.Contains(err.Error(), "no space left") {
// free disk space and retry
}
}
return err
} Prevention
- Always install services with elevated privileges
- Check disk space (df -h) before automated installs
- Remove stale/immutable plists before reinstalling
- Verify MDM/endpoint software does not block writes to /Library/LaunchDaemons
When it happens
Trigger: Calling Generate() (via installLaunchd) where os.WriteFile(resolvedPath, buffer.Bytes(), fileMode) returns an error: EACCES on a read-only or root-owned directory, ENOSPC disk full, or resolvedPath exists as a directory.
Common situations: Installing the service without sudo so /Library/LaunchDaemons is not writable; an existing stale plist with immutable attribute or wrong ownership; disk exhaustion on the system volume; antivirus/MDM blocking writes to LaunchDaemons.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
- error creating %s: %v
- error deleting %s: %v
- error determining executable path: %w
- could not write token to configuration directory: %w
- error generating %s template: %v
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/7e297929a4e1a7c6.
Report an issue: GitHub.