slimtoolkit/slim · error

failed to set log output destination to %q: %w

Error message

failed to set log output destination to %q: %w

What it means

After the touch succeeds, configureLogger opens the log file with os.OpenFile(O_WRONLY|O_CREATE|O_APPEND, 0644) to attach it as logrus output. If the OS refuses to open the file for writing, this wrapped error is returned and the sensor fails to start.

Source

Thrown at pkg/app/sensor/logger.go:36

	logFile string,
) error {
	if err := setLogLevel(enableDebug, levelName); err != nil {
		return fmt.Errorf("failed to set log-level: %v", err)
	}

	if err := setLogFormat(format); err != nil {
		return fmt.Errorf("failed to set log format: %v", err)
	}

	if len(logFile) > 0 {
		// This touch is not ideal - need to understand how to merge this logic with artifacts.PrepareEnv().
		if err := fsutil.Touch(logFile); err != nil {
			return fmt.Errorf("failed to set log output destination to %q, touch failed with: %v", logFile, err)
		}

		f, err := os.OpenFile(logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
		if err != nil {
			return fmt.Errorf("failed to set log output destination to %q: %w", logFile, err)
		}

		log.SetOutput(f)
	}

	return nil
}

func setLogFormat(format string) error {
	switch format {
	case "text":
		log.SetFormatter(&log.TextFormatter{DisableColors: true})
	case "json":
		log.SetFormatter(&log.JSONFormatter{})
	default:
		return fmt.Errorf("unknown log-format %q", format)
	}

View on GitHub (pinned to 81940d17fa)

Solutions

  1. Fix ownership/mode of the log file (chmod 0644 or chown to the sensor's uid).
  2. Ensure the logFile path is a regular writable file, not a directory or broken symlink.
  3. Check 'too many open files' limits if the wrapped error is EMFILE and raise ulimit -n.

Example fix

// before
-rw------- root root /var/log/sensor/sensor.log
// after
chmod 0644 /var/log/sensor/sensor.log && chown sensor:sensor /var/log/sensor/sensor.log
Defensive patterns

Strategy: validation

Validate before calling

func canAppend(path string) error {
    fi, err := os.Stat(path)
    if err != nil { return err }
    if fi.IsDir() { return fmt.Errorf("%s is a directory", path) }
    f, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0644)
    if err != nil { return err }
    return f.Close()
}

Type guard

func isOpenDenied(err error) bool {
    var pe *fs.PathError
    return errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrPermission)
}

Try / catch

if err := Run(ctx); err != nil && strings.Contains(err.Error(), "failed to set log output destination") {
    fmt.Fprintf(os.Stderr, "cannot open log file for append: %v\n", err)
    os.Exit(1)
}

Prevention

When it happens

Trigger: The log file exists but is not writable by the sensor process (wrong owner/mode), the path is a directory, a symlink loop exists, or the fd limit (EMFILE) is reached.

Common situations: Log file pre-created by an init step with restrictive 0600 root ownership; SELinux/AppArmor denying write; log rotation tooling replaced the file with a directory or a read-only link.

Related errors


AI-assisted analysis of slimtoolkit/slim@81940d17fa (2026-08-31). Data as JSON: /api/errors/cfd9a91c24d8e61c. Report an issue: GitHub.